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

Thread: Hardware Quadrature Code for Teensy 3.x

  1. #26
    Teensy3.1 has hardware quadrature counting support, however it is only a 16 bit counter, giving 64K counts. The issue, and the reason for the interrupts is if the system requires more than 64k encoder counts. If your system is always below 64K counts, just reading the counter is okay. Also, if your system is uni-directional it is much simpler. Just read the counter, look at the TOF (Timer Overflow) bit for when to increment the base count by 64K and clear the TOF for next time. As long as you read the counter often enough so that it doesn't overflow twice between reads, it is fairly straightforward.

    The reason for the code is a system with greater than 64K counts and that can change direction at any time. This is a situation that the hardware doesn't handle very cleanly. If you reverse around the overflow region, it gets complicated. And unlike pieces of code where you don't want unscheduled interrupts, you can't temporarily shut off the encoder signal. And then I also have other interrupts to the system of somewhat unknown duration and latency. I don't have a lot of time to spend monitoring the encoders. The quadrature code has interrupts, however, the latency (how soon you have to answer the interrupt) and overhead requirement is fairly low.

    Just monitoring a spinning encoder always going the same direction, you can simplify. If it reverses, you need the code.

    TLB

  2. #27
    I'm not sure what you mean by "serially exporting the count"?
    So the K20 uC in the Teensy has two "Flex Timer Modules" that have a purpose built Quadrature Decode capability. Yes, they use interrupts. But the processor runs at 72Mhz. You would have to be issuing several hundred thousand interrupts per second (encoder transitions) before you would saturate the processor.
    That said, My implementation managed the PID loops to control the DC motors via PWM directly. If you tried to rely on serial interface to send the count and direction to another processor managing the motor... well...

    My first iteration of this design used an I2C based motor driver module from Adafruit. I was keeping the Quadrature decode and PID processing local, but trying to send commands via I2C for the desired PWM value to the motor controller.... Bad idea in retrospect. (Nobody ever accused me of genius) The overhead of sending/receiving/translating I2C messages was not conducive to a responsive servo control, and I could not tame oscillations.
    When I moved the Hbridge for the DC motor to pins in the Teensy directly, I immediately got results.

    Two Quadrature decoders and pid control for both X and Y axis (running end to end of my carriage - 7200 transitions per axis per second) takes less than about 5% CPU cycles and less than 10% memory.
    I have a ton of room to implement two Z axis encoders with pure old school interrupt routines, and add Teacup as well.
    Last edited by unix_guru; 02-19-2015 at 10:11 PM.

  3. #28
    Thank you tlb. Greatly appreciated.

  4. #29
    Junior Member
    Join Date
    Feb 2014
    Posts
    6
    tlb, thanks for the info. I am fairly new to trying to integrate quadrature count into teensy versus offloading to a dedicated IC like this so thanks for the help.

    For my specific application I am building a data logger that writes current pulse count to SD and I expect a maximum pulse count of 39 million from the hardware. Since you stated that the teensy works in 4x count mode, that means I should see around 156 million pulses. I plan to sample at 25Hz. If the device is hooked up upside down (swapping A and B channels) it could "count" negative but it need to be corrected later on (I plan to cross that river when I get to it). I over estimate my max "speed" to be 675000 PPM or 11.25 kHz.

    I will need to play with examples you have on the initial post to get an idea of if this is even possible with my level of understanding. In general though, is my best route something along these lines:
    - Enter subroutine to return count
    - Check overflow flag (to see if 16B limit was reached)
    - If TOF, then add or subtract 65536 to current count
    - Clear TOF
    - Exit subroutine, return count

    Questions:
    1) Without re-zeroing current count every sample interval does that mean I am limited to 32B of counting (16B counter plus one TOF)?
    2) How does TOF work when count is -65537?

    I'm not sure what you mean by "serially exporting the count"?
    I assumed that if the counter was interrupt based and I was mid serial communication during a quadrature count event the total pulse count would be missed because I would be unable to interrupt out of a serial communication once started. I am pretty sure that is not the case from what you guys are describing though.

    Thanks again for the help and I think it would be best for me to try to use the code provided some before I engage anymore on this thread. I know my understanding is lacking on how this all works.

  5. #30
    I am doing something fairly similar - reading an encoder and exporting the count over a serial channel. So your application should fit right in. The calcPosn() method sends back the position as a 32 bit integer, +- 2 billion. I designed for lax interrupt latency requirements. As long as the encoder interrupts are answered every 8K counts you should be okay. So for your application it looks like you just need to get to the interrupts every .5 sec.

    The code handles more complexity than it appears your case has, but you can do the 'bits are cheap and the code is already written' route. If you absolutely do not want interrupts then what you proposed should work. I'm assuming you are uni-directional otherwise there are all sorts of issues.

    Questions:
    1) Without re-zeroing current count every sample interval does that mean I am limited to 32B of counting (16B counter plus one TOF)?
    2) How does TOF work when count is -65537?
    Not sure what you mean by 1).

    For 2), there is a TOFDIR bit that indicates which direction you crossed TOF.

    -TLB

  6. #31
    Junior Member
    Join Date
    Apr 2014
    Posts
    7
    Hi all
    have just come across this thread,describing a solution
    which appears to be an ideal solution for my purposes

    This being to record encoder positions from manually driven high count encoders
    and then send this via DMX to another teensy at some considerable distance.

    So far I have used a megaencoder shield attached to an arduino mega

    and then in turn attempted to wire that shield into a teensy3.1 without much luck.

    Anyhow this code that you have so generously posted appears just the job

    one slight problem at present is that it won't compile on my current setup

    complains about multiple definitions as shown in attached error code

    this is the sketch
    its only the template and # includes
    any suggestions?
    Tia
    harry

    #include <GenEncoder.h>
    #include <QuadDecode.h>
    #include <QuadDecode_def.h>



    void setup() {
    // put your setup code here, to run once:

    }

    void loop() {
    // put your main code here, to run repeatedly:

    }


    error messages attached
    Arduino: 1.6.3 (Mac OS X), TD: 1.22, Board: "Teensy 3.1, Serial, 72 MHz optimized, US English"

    /var/folders/fg/x72zz8415qq21xt0rgm2dt2m0000gn/T/build6191515688651489068.tmp/quadDecode/main.cpp.o: In function `GenEncoder':
    /Users/harryharrison/Documents/Arduino/libraries/quadDecode/QuadDecode_def.h:34: multiple definition of `ftm1_isr'
    /var/folders/fg/x72zz8415qq21xt0rgm2dt2m0000gn/T/build6191515688651489068.tmp/quad_encoder_hard.cpp.o:/Users/harryharrison/Documents/Arduino/libraries/quadDecode/QuadDecode_def.h:34: first defined here
    /Applications/Arduino.app/Contents/Java/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/4.8.4/../../../../arm-none-eabi/bin/ld: Disabling relaxation: it will not work with multiple definitions
    /var/folders/fg/x72zz8415qq21xt0rgm2dt2m0000gn/T/build6191515688651489068.tmp/quadDecode/main.cpp.o: In function `main':
    /Users/harryharrison/Documents/Arduino/libraries/quadDecode/QuadDecode_def.h:38: multiple definition of `ftm2_isr'
    /var/folders/fg/x72zz8415qq21xt0rgm2dt2m0000gn/T/build6191515688651489068.tmp/quad_encoder_hard.cpp.o:/Users/harryharrison/Documents/Arduino/libraries/quadDecode/QuadDecode_def.h:38: first defined here
    /var/folders/fg/x72zz8415qq21xt0rgm2dt2m0000gn/T/build6191515688651489068.tmp/quadDecode/main.cpp.o: In function `IntervalTimer::~IntervalTimer()':
    /Users/harryharrison/Documents/Arduino/libraries/quadDecode/main.cpp:380: multiple definition of `apQDcd2'
    /var/folders/fg/x72zz8415qq21xt0rgm2dt2m0000gn/T/build6191515688651489068.tmp/quad_encoder_hard.cpp.o:/Users/harryharrison/Documents/Arduino/libraries/quadDecode/QuadDecode_def.h:34: first defined here
    /var/folders/fg/x72zz8415qq21xt0rgm2dt2m0000gn/T/build6191515688651489068.tmp/quadDecode/main.cpp.o: In function `IntervalTimer::~IntervalTimer()':
    /Users/harryharrison/Documents/Arduino/libraries/quadDecode/main.cpp:380: multiple definition of `apQDcd1'
    /var/folders/fg/x72zz8415qq21xt0rgm2dt2m0000gn/T/build6191515688651489068.tmp/quad_encoder_hard.cpp.o:/Users/harryharrison/Documents/Arduino/libraries/quadDecode/QuadDecode_def.h:34: first defined here
    collect2: error: ld returned 1 exit status
    Error compiling.

    This report would have more information with
    "Show verbose output during compilation"
    enabled in File > Preferences.

  7. #32
    This is due to the use of templates in the code. Templates are used to allow the same logical code for both decoder channels (separate hardware). The compiler must see QuadDecode_def.h only once otherwise it makes multiple copies. It is generally included in main.cpp. Also QuadDecode_def.h includes QuadDecode.h so this does not have to be explicitly included.

    I have avoided the need to become familiar with Arduino compile sequences, so I don't know the best way to solve your problem with Arduino, but it is related to template compile issues.

    TLB

  8. #33
    Junior Member
    Join Date
    Apr 2014
    Posts
    7
    Thanks for your response,
    new thing to learn now
    will report how I go

  9. #34
    I am in way over my head on this stuff. I have been trying his original code ran compiled the main.cpp in the arduino IDE with all necessary files included and keep getting 1's for forward motion and -1's for reverse.

    I know it's working, but I am wondering how I can properly add the 1's at each interrupt so that it can count up or down. I suppose it has to happen after the serial printout of the variable, but I am totally at a loss. I have a long way to go on this, but no matter what I try, I see no results. PLEASE advise, guys.

    Here's how I had it the other day after I stripped down the code for testing (didn't use the GenEncode stuff because I know I have a working encoder).

    Here's what I wrote for my test:
    Code:
    
    
    #define GEN_ENCODER		// Include encoder test signals code
    
    
    
    #include "WProgram.h"
    
    #include "QuadDecode_def.h"
    
    #ifdef GEN_ENCODER
    
    #include "GenEncoder.h"
    
    #endif
    
    #include <stdbool.h>
    
    
    
    // Timing for GUI update time, how often send back data values
    
    #define GUI_UPDATE_TIME	 250000	// 200 mSec update
    
    
    
    // Command headers for X,Y,Z data channels
    
    const char cmd1[] = "RX";
    
    const char cmd2[] = "RY";
    
    const char cmd3[] = "RZ";
    
    const char cmd4[] = "LX";
    
    const char cmd5[] = "LY";
    
    const char cmd6[] = "LZ";
    
    const char* cmdPointers[]= {cmd1,cmd2,cmd3,cmd4,cmd5,cmd6};
    
    
    
    const uint8_t num_cmds = 6;	// Generated Postition in latched position
    
    //const uint8_t num_cmds = 3;		// Only send up RXYZ continually
    
    
    
    // Variables from CMM program
    
    volatile int32_t rtX=0, rtY=0, rtZ=0;	// Realtime values of X,Y,Z
    
    volatile int32_t ltX=0, ltY=0, ltZ=0;	// Latched values of X,Y,Z
    
    
    
    volatile bool zero_rtX=0, zero_rtY=0, zero_rtZ=0;   // Zero values of X,Y,Z
    
    
    
    volatile bool doOutput=false;	// Run output routine
    
    
    
    IntervalTimer serialTimer;	// How often to update serial
    
    
    
    // Generate test encoder signals
    
    #ifdef GEN_ENCODER
    
    /*struct GenEncData{
    
        int32_t maxPosn;
    
        int32_t minPosn;
    
        int32_t cycleMax;
    
        int32_t cycleMin;
    
        int32_t cycleCenter;
    
        int cycleCrossings;
    
        int bigCrossings;
    
    };*/
    
    
    
    const int ENCOUT1_A = 9;    // Pinouts
    
    const int ENCOUT1_B = 10;
    
    const int32_t ENC_UPDATE_TIME1 = 433;    // uSec 
    
    
    
    GenEncData genEncData1 ={95000,-25000,10,-10,0,100,2};
    
    
    
    GenEncoder genEnc1(ENCOUT1_A,ENCOUT1_B,ENC_UPDATE_TIME1,genEncData1,0);
    
    
    
    const int ENCOUT2_A = 15;   // Pinouts
    
    const int ENCOUT2_B = 14;
    
    const int32_t ENC_UPDATE_TIME2 = 70;    // uSec
    
    GenEncData genEncData2 ={120000,-66000,10000,-25000,24576,4,3};
    
    
    
    GenEncoder genEnc2(ENCOUT2_A,ENCOUT2_B,ENC_UPDATE_TIME2,genEncData2,1);
    
    #endif
    
    
    
    void timerInt(void);	// Main timing loop interrupt
    
    
    
    QuadDecode<1> xPosn;	// Template using FTM1
    
    QuadDecode<2> yPosn;	// Template using FTM2
    
    
    
    
    
    extern "C" int main(void)
    
    {   
    
    	//bool LED_ON=false;
    
    
    
    	char inbuf[3];  // Characters to be received
    
    	char inByte;
    
    	int32_t buffer[6];  // Values to send, X,Y,Z realtime and latched
    
    	uint8_t n;	    // Number of characters received
    
    	uint8_t j;
    
    
    
    	Serial.begin(115200); // USB is always 12 Mbit/sec
    
    
    
    	xPosn.setup();	    // Start Quad Decode position count
    
    	yPosn.setup();	    // Start Quad Decode position count
    
    
    
    	// Start encoder test signal generation
    
    #ifdef GEN_ENCODER
    
    	genEnc1.start();
    
    	genEnc2.start();
    
    #endif
    
    
    
    	serialTimer.begin(timerInt,GUI_UPDATE_TIME);	// GUI Update time
    
    
    
    
    
    	xPosn.start();	    // Start Quad Decode position count
    
    	yPosn.start();	    // Start Quad Decode position count
    
    
    
    	    while (1) {
    
    		if (doOutput){
    
    		    doOutput=false;
    
    
    
    		    // Read in string to zero axis
    
    		    if (Serial.available()){
    
    			while (Serial.available()){
    
    			    inByte=Serial.read();
    
    			    if (inByte == 'Z'){	    // Start byte detected
    
    				for(n=0;n<3;n++){  //    read in string
    
    				    inbuf[n]=Serial.read();
    
    				}
    
    			    }
    
    			}
    
    			// Echo value back for diagnostics
    
    			Serial.print("MSByteReceived is ");
    
    			for(int8_t ib =0; ib < 3; ib++){
    
    			    Serial.write(inbuf[ib]);
    
    			}
    
    			Serial.println(" ");
    
    		    };
    
    
    
    		    // Determine if need to zero input
    
    
    
    		    // Zero axis posn from GUI
    
    		    if (inbuf[0]=='1'){
    
    		       	zero_rtX=true;
    
    			inbuf[0]='0';
    
    		    }
    
    		    else zero_rtX=false;
    
    
    
    		    if (inbuf[1]=='1'){
    
    		       	zero_rtY=true;
    
    			inbuf[1]='0';
    
    		    }
    
    		    else zero_rtY=false;
    
    
    
    		    if (inbuf[2]=='1'){
    
    		       	zero_rtZ=true;
    
    			inbuf[2]='0';
    
    		    }
    
    		    else zero_rtZ=false;
    
    		    
    
    		    if (zero_rtX ){
    
    #ifdef GEN_ENCODER
    
    			genEnc1.setZero();
    
    #endif
    
    			xPosn.zeroFTM(); 			
    
    		    }
    
    		    rtX=xPosn.calcPosn();
    
    
    
    		    if (zero_rtY ){
    
    #ifdef GEN_ENCODER
    
    			genEnc2.setZero();
    
    #endif
    
    			yPosn.zeroFTM(); 			
    
    		    }
    
    		    rtY=yPosn.calcPosn();
    
    		    
    
    		    if (zero_rtZ ){
    
    			rtZ=0;
    
    		    }
    
    
    
    		    // Set Generated value in latched position for debug
    
    		    ltX=genEnc1.getPosn();  // X generated position
    
    		    ltY=genEnc2.getPosn();  // Y generated position
    
    
    
    		    // Send out axis values
    
    		    buffer[0] = rtX;
    
    		    buffer[1] = rtY;
    
    		    buffer[2] = rtZ;
    
    		    buffer[3] = ltX;
    
    		    buffer[4] = ltY;			
    
    		    buffer[5] = ltZ;
    
        
    
    		    Serial.println("MSTeensy Loop");	
    
    		    
    
    		    // Send out rtX, rtY, rtZ values
    
    		    for (j=0;j<num_cmds;++j){
    
    			    Serial.print(cmdPointers[j]);
    
    			    Serial.println(buffer[j]);
    
    
    
    		    }
    
    
    
    		    Serial.println("MSEnd of Loop");	
    
    
    
    		}
    
    	    }
    
    
    
    }
    
    void timerInt(void){
    
        doOutput=true;
    
    }

  10. #35
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    16,269
    Quote Originally Posted by harryprayiv View Post
    I know it's working, but I am wondering how I can properly add the 1's at each interrupt so that it can count up or down.
    Have you tried simply running the regular Encoder library? Even if that's not your end goal, maybe trying it with those 2 pins can at least build some confidence the hardware is really right?

  11. #36
    Quote Originally Posted by PaulStoffregen View Post
    Have you tried simply running the regular Encoder library? Even if that's not your end goal, maybe trying it with those 2 pins can at least build some confidence the hardware is really right?

    I know that the encoder is working flawlessly because I have seen the quadrature signal from my encoders on an oscilloscope. I compared the original signal (5V to the 3.3V conversion with a logic level convertor) and there may have been a SLIGHT delay introduced by the MOSFETs but it is not enough to screw with my quadrature signal.



    I have tried just about every permutation. Is there somewhere that I am supposed to set the variables of my encoders (the resolution and other stuff) before compiling the sketches?

    Here's the code that I am running:
    Code:
    /* Encoder Library - Basic Example
     * http://www.pjrc.com/teensy/td_libs_Encoder.html
     *
     * This example code is in the public domain.
     */
    
    #include <Encoder.h>
    
    // Change these two numbers to the pins connected to your encoder.
    //   Best Performance: both pins have interrupt capability
    //   Good Performance: only the first pin has interrupt capability
    //   Low Performance:  neither pin has interrupt capability
    Encoder myEnc(3, 4);
    //   avoid using pins with LEDs attached
    
    void setup() {
      Serial.begin(9600);
      Serial.println("Basic Encoder Test:");
    }
    
    long oldPosition  = -999;
    
    void loop() {
      long newPosition = myEnc.read();
      if (newPosition != oldPosition) {
        oldPosition = newPosition;
        Serial.println(newPosition);
      }
    }
    I have the encoder connected to pins 3 and 4 and it is causing the "basic" sketch by PJRC to return these values in the serial monitor:
    Code:
    1
    0
    -1
    0
    1
    0
    1
    0
    -1
    0
    -1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    1
    0
    -1
    0
    1
    0
    It appears to me that it is reading the pulses but it is not actually adding them together. I am SO very confused on this one. It's sad because this is the first step in my project (after getting the circuit hooked up properly). The encoders are 5V, so I had to run them through a logic level convertor just to be safe and reduce slew. I am just about ready to put this project down for a while since this initial step has been so tough and out of reach.

  12. #37
    Are your grounds hooked up correctly? You get this kind of a pattern when one encoder line is not toggling. One line goes high, counts 1, same line goes low again, counts down again. The line may be toggling but have some kind of an offset such that it never goes below the switching threshold.

    And it looks like both sets of code give similar results; both are saying one encoder line has a problem.

    Teensy3.1 inputs are 5 V compatible so you can run 5V encoder lines directly into the part. A very nice feature.

    TLB

  13. #38
    The MOSFET circuit inline was indeed the culprit. Your suggestion fixed my problem. Thank you so very much for that. I now have the hardware code working on my encoder.

    I'm wondering, though, what could I do to bring the voltage to nominal levels without adding slew or delay (the likes of which caused my problem here)? I tried (and failed) at translating logic level voltages but I still want to make sure I'm not hurting the Teensy in the long run.

  14. #39
    Senior Member xxxajk's Avatar
    Join Date
    Nov 2013
    Location
    Buffalo, NY USA
    Posts
    456
    Interesting, Not that i would use this for an optical encoder though, since you can get a nice 4x resolution on optical easily, and you would not have to debounce, etc.
    For a mechanical encoder this code seems fine, but for optical, I would do a lot different-- and it would allow higher rates too.

  15. #40
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    16,269
    Quote Originally Posted by harryprayiv View Post
    I'm wondering, though, what could I do to bring the voltage to nominal levels without adding slew or delay (the likes of which caused my problem here)? I tried (and failed) at translating logic level voltages but I still want to make sure I'm not hurting the Teensy in the long run.
    Teensy 3.1 is 5V tolerant, so if you signal is always between zero to 5V, it's within the spec.

    If you were using that mosfet plus 2 resistor circuit, which Adafruit, Sparkfun and others promote as universally useful for all 3-5V level translation, I'd be amazed it it worked. It's really terrible for any sort of high speed signal. Worst yet, it badly distorts signals, because the high to low transition is fast, but low to high is very slow. I've ranted on this many time... but I will again... I believe those companies do everyone a huge disservice by promoting that mosfet circuit as useful for nearly all level translation. In practice, it's really only great for I2C protocol. It's terrible for almost everything else!

    If you *really* want to translate it to 3.3V, perhaps a chip like a 74LCX125 might be useful? It has excellent performance, with delay under 6ns, and equal delay to propagate both low to high and high to low. The 6 buffers within a single chip have a maximum skew (differing delay) of only 1ns.

  16. #41
    Thanks for the info. It sucks that there is so much misinformation out there (and certainly my oscilloscope looked like it was getting the right signal for this to work).

    I will eventually look into that 74LCX125 for the final version of this project, perhaps.



    I am now moving onto a similar step to what was mentioned in the first part of this post: sending those encoder values via i2c.

    I assume that I should just use i2c convention similarly to how his serial debug is handled in the main.cpp that tlb so generously posted, but I am reading elsewhere on this forum that Teensy 3.1 can't send i2c values as slave while running code with interrupts built in. This would mean that I would be forced to run the i2C as master from the quad decode Teensy 3.1 and would prevent me from networking a bunch of Teensy 3.1's (each for around 2 axis of an unknown final number) to a main teensy 3.1.

    I am now only at the second part of this project, but if I comprehend this correctly, my idea that I could use an interrupt with the FTM1 and FTM2 to read quad values (from maybe two separate encoders) and send those out via i2c to a main, number crunching Teensy 3.1 may have been misinformed.

    My idea was simple:
    1. read values
    2. send values to main microcontroller via i2c where those values can be converted (in my case, to quaternion values) and then sent out via RC or bluetooth via USB or SDI.

  17. #42
    I am reading elsewhere on this forum that Teensy 3.1 can't send i2c values as slave while running code with interrupts built in.
    I don't know where you read this, but I have two Teensy's running my QuadDecode code - two encoder channels on one Teensy and the third on a 2nd Teensy. I communicate between the two with I2C. The one with two channels is the master and the one with the third channel is the slave. I am using the standard Wire.h code. It works just fine.

    If you are back to using my code, just do:
    Code:
    	    rtX=xPosn.calcPosn();
    	    rtY=yPosn.calcPosn();
    to get the x and y position values.(Or whatever your preferred variable names are) There is probably no reason to do your processing on a separate Teensy. The code is designed to have very low interrupt latency requirements and has a low processing overhead. All the work is done in the FTM hardware, with the program only being interrupted about every 8K encoder edges to deal updating position and direction. If you have multiple interrupts with high latency requirements or that have long interrupt servicing routines your above statement may be true, but that is not the case with this code. And there is plenty of processing capability left on the Teensy doing encoder processing.

    TLB

    P.S. One one Teensy I have 3 Interval Timers, USB Serial and I2C Master running. Reading 3 channels and sending them back over serial. And generating sample encoder signals when just testing.

  18. #43
    I don't know where you read this, but I have two Teensy's running my QuadDecode code - two encoder channels on one Teensy and the third on a 2nd Teensy. I communicate between the two with I2C. The one with two channels is the master and the one with the third channel is the slave. I am using the standard Wire.h code. It works just fine.
    I'm pleased to hear that. I will get back to work, then.

    I want to do the math on another unit because my needs are such that I want all of my controllers to be able to send data into a central unit (originally planned to be a UDOO, but now it'll probably be a Teensy 3.1) where the signal can be changed to suit the application. I am also doing it for the sake of modularity and expandability.

    For example, I want to be able to select a "mode" and have the encoder signals generate a different number based on the application. Currently, I plan to do MIDI, DMX, USB, RC/Brushless gimbal angle data, Quaternion, Bluetooth, ArtNet, and others while sending the exact same numbers in.....unless you happen to know how to reprogram a Teensy from another teensy on the fly.
    _____________
    I'm adding in a zero-ing button and a bit of code that checks whether or not my wheels are connected.

    Is there a way to enable 4X counting mode on this code (I am using your original main.cpp directly) or is it already doing 4X counts? The reason I ask is because my encoders are SUPPOSEDLY 1024 PPR, but I only get around 1024 total counts out of them. I don't need the speed most of you need, but I would like the accuracy of 4096 PPR rather than 1024.
    It might be nice to do a 4X mode so that I can have 4096 PPR for utmost positional accuracy. No big deal if not, I'm just curious.
    Last edited by harryprayiv; 06-07-2015 at 05:55 AM. Reason: clarity

  19. #44
    Is there a way to enable 4X counting mode on this code (I am using your original main.cpp directly) or is it already doing 4X counts? The reason I ask is because my encoders are SUPPOSEDLY 1024 PPR, but I only get around 1024 total counts out of them. I don't need the speed most of you need, but I would like the accuracy of 4096 PPR rather than 1024.
    It might be nice to do a 4X mode so that I can have 4096 PPR for utmost positional accuracy. No big deal if not, I'm just curious.
    Its always 4x, the only option. You are probably interpreting your spec's wrong. PPR is pulses per revolution, versus LPR, lines per revolution. The PPR number already assumes the 4x reading. Welcome to the world of specsmanship.

  20. #45
    Quote Originally Posted by tlb View Post
    Its always 4x, the only option. You are probably interpreting your spec's wrong. PPR is pulses per revolution, versus LPR, lines per revolution. The PPR number already assumes the 4x reading. Welcome to the world of specsmanship.
    Thanks for the info.
    I was afraid of that. Oh well.

    I may upgrade to 1024 LPR eventually for a 4096 set, but I think it'll be fine for now.

    So far, I am way closer to getting this working as I had envisioned only three months ago thanks to you. I will start a new thread once I do.

    For cases like mine, would you recommend I try and implement some sort of near real-time smoothstep() algorithm to prevent "stair-stepping" on angular data that I send to the gimbal? I want this to be able to gear down to a nice perceived resolution for the camera operator. I was talking to a Libra tech, the other day and apparently, they are 1024 LPR/ 4096 PPR.

  21. #46
    Junior Member
    Join Date
    Oct 2015
    Posts
    2

    Stripped down and arduino-fied / Teensy-fied

    Stripped out version, It works great, but I am defenetly not an expert so it is delivered "as is"
    Code:
    /*This is a stripped down code. original owner Mr TLB https://forum.pjrc.com/members/34765-tlb
    found at forum post: https://forum.pjrc.com/threads/26803-Hardware-Quadrature-Code-for-Teensy-3-x
    For decoding quadrature encoders in hardware on the Teensy 3.1 and Teensy 3.2
    Pinout: Enc 1 = pin 3 and pin 4   Enc 2 = pin 32 and pin 25*/
    
    #include "WProgram.h"
    #include "QuadDecode_def.h"
    #include <stdbool.h>
    
    QuadDecode<1> xPosn;  // Template using FTM1
    QuadDecode<2> yPosn;  // Template using FTM2
    
    void setup()
    {   
      Serial.begin(9600); // USB is always 12 Mbit/sec
    
      xPosn.setup();      // Start Quad Decode position count
      yPosn.setup();      // Start Quad Decode position count
    
      xPosn.start();      // Start Quad Decode position count
      yPosn.start();      // Start Quad Decode position count
    }
          void loop() 
          {
            if(!(millis()%20)) //Print out every 20mS
            {
             Serial.print("x ");   Serial.print(xPosn.calcPosn());
             Serial.print("\t\t");
             Serial.print("y "); Serial.println(yPosn.calcPosn());
            }
            
            if(!(millis()%10000)) //zero X and Y counter every 10 second
            {
             xPosn.zeroFTM(); //Zero Xposition counter
             yPosn.zeroFTM(); //Zero Yposition counter
            }
          }

  22. #47
    Junior Member
    Join Date
    Nov 2015
    Posts
    2
    Hi,

    I'm new to the party, but can anyone explain where the limitation of having 2 encoders max comes from ?

    Thanks,

    Pat

  23. #48
    Junior Member
    Join Date
    Oct 2015
    Posts
    2
    Quote Originally Posted by ptr View Post
    Hi,

    I'm new to the party, but can anyone explain where the limitation of having 2 encoders max comes from ?

    Thanks,

    Pat
    Hi, there is only two channels available in HARDWARE. You can add many more in SOFTWARE.

  24. #49
    Junior Member
    Join Date
    Nov 2015
    Posts
    2
    Ah I see. So I can use the code from here: https://www.pjrc.com/teensy/td_libs_Encoder.html and connect 17 encoders to the 34 pins of the Teensy 3.2 ?

  25. #50
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    16,269
    Pin 13 has the LED, so you can only use that pin if your signal is a strong digital logic signal capable of driving the LED. A regular mechanical encoder or open collector type which requires a pullup can't be used on pin 13.

    Otherwise, yes, in theory you can connect 17 encoders with that library. I'm not aware of anyone actually connecting that many. If you do, I hope you'll let me know how it goes... and post a photo!

Posting Permissions

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