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

Thread: ILI9341 and encoders in an Electronic Lead Screw Application

  1. #1

    ILI9341 and encoders in an Electronic Lead Screw Application

    I'm attempting to come up with an electronic lead screw for my lathe using a Teensy 4.1. So I am working out some of the critical pieces. My code only implements one case at a time, and there is no way to change things, at the moment. A UI will come later. If the basics don't work then an UI won't matter! Anyways, I am using QuadEncoder, TeensyTimerTool and have added in the touch display that PJRC sells, the ILI9341. I am using an Omron E6B2-CWZ6C rotary encoder, and am directly pulsing a cheapo TB67S109AFTG based full bridge driver for a NEMA-11 stepper. When I work out some of my system better, I will upgrade the stepper driver and use a 4Nm NEMA-24 stepper.

    If I use serial output to the TeensyMonitor, everything looks really good, no missing counts at encoder speeds that I care about (< 1200 RPM, with a 4096 count/rev rotary encoder). The stepper motor appears to increment correctly and follow the encoder, no matter the encoder shaft speed, nor direction. This pretty much changes using the tft display. The main loop appears to be missing counts, as many as 9 counts. I don't think the HW encoder is actually missing counts (but I can't prove that yet) but it may be that by the time the tft function has returned, the encoder value has changed by N counts. It's easy to correct for a count or two, but it gets increasingly difficult as the apparent skipped counts increases, say to 9 or 10! It is important for the stepper to keep up with the encoder, and to maintain the proper ratio of steps to encoder counts, or the lathe will create faulty threads of varying pitch.

    So, I am wondering if there are more efficient, or at least lower blocking time way to write to the display. I don't mind a frame rate of 2-5 Hz, as it isn't critical to me. But I do mind a lot if the display writes are preventing the rest of my code to operate at speed. Is there some sort of frame buffer mode, or line mode that is a fire and forget process? Does the ILI9341_t3n use DMA by default? It's quite likely I am using the library incorrectly, as I am new to the Teensy landscape.

    What is the best way to attach the project? It's not that big, but it is four files. Should I just zip the directory and attach? I will try that. Please advise if there is a better recommended way.
    stepper_n_encoder.zip
    With tft enabled
    Code:
    Touchscreen started
    Touchscreen started
    
        5.1 RPM 
    
       14.6 RPM 
    
       30.0 RPM 
    
       41.0 RPM 
    Fault! bb = 2
    Err cnt : 1
    
       43.2 RPM 
    Fault! bb = 2
    Err cnt : 2
    
       42.5 RPM 
    Fault! bb = 2
    Err cnt : 3
    
       49.1 RPM 
    Fault! bb = 3
    Err cnt : 4
    
       68.1 RPM 
    Fault! bb = 5
    Err cnt : 5
    
      153.1 RPM 
    Fault! bb = 9
    Err cnt : 6
    
      147.9 RPM 
    Fault! bb = 7
    Err cnt : 7
    
      118.7 RPM 
    Fault! bb = 6
    Err cnt : 8
    
       91.6 RPM 
    Fault! bb = 5
    Err cnt : 9
    
       79.1 RPM 
    Fault! bb = 4
    Err cnt : 10
    
       76.2 RPM 
    Fault! bb = 4
    Err cnt : 11
    
       79.8 RPM 
    Fault! bb = 4
    Err cnt : 12
    
       82.8 RPM 
    Fault! bb = 5
    Err cnt : 13
    
       99.6 RPM 
    Fault! bb = 6
    Err cnt : 14
    
      104.7 RPM 
    Fault! bb = 6
    Err cnt : 15
    
       98.1 RPM 
    Fault! bb = 4
    Err cnt : 16
    
       79.8 RPM 
    Fault! bb = 4
    Err cnt : 17
    
       63.7 RPM 
    Fault! bb = 3
    Err cnt : 18
    
       64.5 RPM 
    Fault! bb = 4
    Err cnt : 19
    
       80.6 RPM 
    Fault! bb = 4
    Err cnt : 20
    
       93.8 RPM 
    Fault! bb = 5
    Err cnt : 21
    
      103.3 RPM 
    Fault! bb = 4
    Err cnt : 22
    
       40.3 RPM 
    
       10.3 RPM 
    
       -0.7 RPM 
    
       -0.7 RPM 
    
        1.5 RPM 
    
        0.7 RPM 
    
        2.9 RPM 
    
       13.9 RPM 
    
       21.2 RPM 
    Fault! bb = 2
    Err cnt : 23
    
       35.9 RPM 
    Fault! bb = 2
    Err cnt : 24
    
       34.4 RPM 
    Fault! bb = 2
    Err cnt : 25
    
       53.5 RPM 
    Fault! bb = 4
    Err cnt : 26
    
       75.4 RPM 
    Fault! bb = 4
    Err cnt : 27
    
      101.1 RPM 
    Fault! bb = 7
    Err cnt : 28
    
      133.3 RPM 
    Fault! bb = 7
    Err cnt : 29
    
      106.9 RPM 
    Fault! bb = 5
    Err cnt : 30
    
       93.0 RPM 
    Fault! bb = 5
    Err cnt : 31
    
       93.8 RPM 
    Fault! bb = 5
    Err cnt : 32
    
       84.2 RPM 
    Fault! bb = 4
    Err cnt : 33
    Without writes to tft
    Code:
    Touchscreen started
    Touchscreen started
    
        0.7 RPM 
    
        1.5 RPM 
    
        8.1 RPM 
    
       18.3 RPM 
    
       27.1 RPM 
    
       29.3 RPM 
    
       33.7 RPM 
    
       57.1 RPM 
    
      126.7 RPM 
    
      153.1 RPM 
    
      188.2 RPM 
    
      210.9 RPM 
    
      186.8 RPM 
    
      142.8 RPM 
    
      158.9 RPM 
    
      189.0 RPM 
    
      210.9 RPM 
    
      122.3 RPM 
    
        1.5 RPM 
    
       -0.7 RPM 
    
        0.7 RPM 
    
        2.2 RPM 
    
       21.2 RPM 
    
       59.3 RPM 
    
       45.4 RPM 
    
       45.4 RPM 
    
       51.3 RPM 
    
       76.2 RPM 
    
      175.8 RPM 
    
      178.7 RPM 
    
      129.6 RPM 
    
      122.3 RPM 
    
      211.7 RPM 
    
      276.1 RPM 
    
      467.3 RPM 
    
      387.5 RPM 
    
        0.7 RPM 
    
       -0.7 RPM 
    
        0.7 RPM 
    
        2.2 RPM 
    
       26.4 RPM 
    
       41.7 RPM 
    
       54.9 RPM 
    
       74.0 RPM 
    
      134.0 RPM 
    
      202.9 RPM 
    
      282.0 RPM 
    
      367.7 RPM 
    
      392.6 RPM 
    
       54.2 RPM 
    
       -0.7 RPM 
    
        0.7 RPM 
    
       -0.7 RPM 
    
       -8.8 RPM 
    
      -30.0 RPM 
    
      -38.1 RPM 
    
      -15.4 RPM 
    
      -41.7 RPM 
    
      -87.2 RPM 
    
     -145.8 RPM 
    
     -358.2 RPM 
    
     -338.4 RPM 
    
     -457.0 RPM 
    
     -484.9 RPM 
    
      -16.8 RPM 
    
       -1.5 RPM 
    
      -16.1 RPM 
    
      -50.5 RPM 
    
     -155.3 RPM 
    
     -261.5 RPM 
    
     -344.2 RPM 
    
     -571.3 RPM 
    
     -189.0 RPM 
    
        0.7 RPM 
    
        0.7 RPM 
    
        0.7 RPM 
    
        1.5 RPM 
    
       16.1 RPM 
    
       41.7 RPM 
    
       50.5 RPM 
    
       68.1 RPM 
    
       71.0 RPM 
    
       84.2 RPM 
    
      186.0 RPM 
    
      329.6 RPM 
    
      317.1 RPM 
    
      231.4 RPM 
    
        8.1 RPM 
    
        5.9 RPM 
    
       36.6 RPM 
    
       79.8 RPM 
    
      153.8 RPM 
    
      372.1 RPM 
    
      356.7 RPM 
    
      444.6 RPM 
    
      143.6 RPM 
    
       -6.6 RPM 
    
      -30.8 RPM 
    
      -47.6 RPM 
    
      -54.9 RPM 
    
     -138.4 RPM 
    
     -280.5 RPM 
    
     -415.3 RPM 
    
     -618.9 RPM 
    
     -263.7 RPM 
    
       -5.9 RPM
    Developed in Arduino 1.8.19, Teensy Loader 1.56. Ubuntu 20.04.4 LTS. Picture of mess on my desk!
    Click image for larger version. 

Name:	PXL_20220514_162001728_720.jpg 
Views:	14 
Size:	162.2 KB 
ID:	28363

  2. #2
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    If you don't find a possibility to do non blocking writes to the display you might consider a different approach:

    If you can assure that the number of encoder counts per spindle rev is always more than the number of required stepper pulses per leadscrew rev, you could do the following:

    • Monitor the encoder in the background
    • On each change of the encoder use Bresenhams algorithm to decide if a step needs to be done. If so, do the step, if not, do nothing.

    This will give you a "stiff" relation of encoder counts to stepper pulses which you need for your leadscrew.
    Since the encoder monitoring and step pulse generation runs in the background (interrupt based), blocking writes to the display won't matter.

    Your encoder count rate is only moderate (20 rev/s * 4800 cnts/rev = 96000 cnts/sec). So, there is no real need to use the HW counters. If you use the EncoderTool (https://github.com/luni64/EncoderTool), you can configure it to invoke a callback function on each change of the encoder (Maybe you can do the same for the HW counters?). You then can conveniently do the Bresenham and step generation in the callback which should decouple you from long running blocking code in the foreground.

    You find information about Bresenhams algorithm in WikiPedia. You can also have a look at my implementation in TeensyStep where I use this algorithm to move steppers in sync:https://github.dev/luni64/TeensyStep...rolBase.h#L116. The leadMotor would correspond to your spindle-Encoder, the slave motor would be your stepper for the leadscrew

    What is the best way to attach the project?
    I personally prefer a GitHub repo for projects containing more than one file. Just send a link to the repo or specific code (as I did above). If someone wants to try one can simply clone the repo. Of course you can also zip your project and attach it here...
    Last edited by luni; 05-14-2022 at 06:06 PM.

  3. #3
    Thanks for replying @luni. Yes, the number of encoder counts per spindle revolution is always more than the number of required stepper pulses per lead screw revolution.
    I do monitor the count in the main loop, and do Bresenham's algorithm. For every single positive single count of the encoder, I add N to an accumulator, if the accumulator is greater than the denominator D, I subtract D. N and D are defined as
    Code:
    leadscrewpitch = 25.4/leadscrewTPI  # in mm
    N = mypitch * basestep * microstepsperstep
    D = leadscrewpitch * encoder_res
    for metric threads. N/D < 1.

    I need to look at the HW counters. QuadEncoder does have ISRs which are invoked as a the result of a change in the HW counters. It does update the encoder count. I cannot tell at this time if it is missing any counts, but I doubt it.
    Might not be implementing Bresenham correctly, but the stepper does seem to follow the encoder ok - as long as I don't write to the ILI9341 during the main loop. However, I think the HW count is right.

    Thanks for your ideas, I will check out your EncoderTool. I will also check to see if I can do Bresenham and step generation in a callback. It's a different way of looking at the problem, and I appreciate your insights!
    Last edited by clinker8; 05-14-2022 at 06:37 PM. Reason: formatting

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    I will also check to see if I can do Bresenham and step generation in a callback. It's a different way of looking at the problem,
    The nice thing about this approach is, the whole thing runs completely in the background. Your foreground code can do whatever it wants, as long as it doesn't disable interrupts your leadscrew will magically follow your spindle :-)

    This should give you a head start with the EncoderTool.

    Code:
    #include "Arduino.h"
    #include "EncoderTool.h"
    
    using namespace EncoderTool;
    
    Encoder SpindleEnc;
    
    void onEncoderChanged(int value, int delta)  
    {
        // bresenham goes here
        // if necessary do a step
        // you won't need the value, but you can use delta to determine spindle direction (delta = +/-1)
    }
    
    
    void setup()
    {
        SpindleEnc.begin(2,3, CountMode::full); // encoder on pin 2,3 count all edges of the quadrature signal
        SpindleEnc.attachCallback(onEncoderChanged);
    }
    
    void loop()
    {
        Serial.println(millis());
        delay(250);  // simulate something blocking
    }

  5. #5
    Trying to implement your suggestions. Made version 2.

    @luni, is there a way to readback the count value at a moment in time? I want to estimate RPM and I know the count when I enter the onEncoderChanged callback but not some other arbitrary time?
    I'd like to save the value at time t1, in the main loop? then execute a 20ms timer, and read the value at that time t2 (= t1 + 20ms), then counts/second = 50*(val2 - val1). Or is there a better way to do this?

  6. #6
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Sure, something like this should work (untested, first value will be wrong)

    Code:
    #include "Arduino.h"
    #include "EncoderTool.h"
    
    using namespace EncoderTool;
    
    Encoder spindleEnc;
    IntervalTimer speedTimer;
    volatile float currentSpeed = 0;
    
    void onEncoderChanged(int value, int delta)
    {
        // bresenham goes here
        // if necessary do a step
        // you won't need the value, but you can use delta to determine spindle direction (delta = +/-1)
    }
    
    void onSpeedTimer()
    {
        static uint32_t c0;
    
        uint32_t c1 = spindleEnc.getValue();
        currentSpeed =  (c1 - c0)/0.02f;  // cts per second
        c0 = c1;
    }
    
    void setup()
    {
        spindleEnc.begin(2,3, onEncoderChanged, CountMode::full); // encoder on pin 2,3, attach callback,  count all edges of the quadrature signal  
        speedTimer.begin(onSpeedTimer, 20'000); // call onSpeedTimer every 20ms
    }
    
    void loop()
    {
        Serial.println(currentSpeed);
        delay(250);  // simulate something blocking
    }
    Last edited by luni; 05-15-2022 at 06:02 PM.

  7. #7
    @luni, This code stub doesn't seem to work. If I print out c1 and c0, they either are the same, or only differ by one count, independent of the physical encoder shaft RPM. spindleEnc.getValue is not working as I would expect.

    However, I did get it to work using a one shot timer. And now it works with the tft display! It is not apparent if I am losing any counts. How can I check for this?

    The HW Quadrature library and this encoder tool have opposite senses of rotation. HW QuadEncoder tool matches the rotation of the encoder, but this EncoderTool is reversed, for no change in wiring. I can fix it in my code, but thought I would point this out.

    I am very excited that I got this part working. Thanks for helping out! Now I can ponder more of the system...

  8. #8
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,557
    As for the display it may depend on what you are doing and the like, which library and how you are using it.

    Sounds like you are using my: ILI9341_t3n

    No it does not use DMA by default. You need to tell it to use a frame buffer:
    There are more details up on the readme file of the project... Probably still need lots more details but...

    You can enable frame buffer by calling: tft.useFrameBuffer(true);
    which if you have not already done so will allocate memory for the frame buffer.
    There is another method that allows you to set your own.

    You then can all all of the graphic primitives and the output will go into the frame buffer.

    You can still update the screen without using DMA by calling: tft.update();

    You can however update the screen with tft.updateScreenAsync()
    There is an option to have it continuously run the DMA to the screen, but it eats up the SPI...
    Plus you may then need/want to do additional things to synchronize your outputs to the screen to have things consistent...
    So would not do continuous unless you were doing things like movie output, and you field callback for frame complete and half frame and you update the part that is not being refreshed...

    Hope that is enough to get you started.

  9. #9
    @KurtE yes, I am using your library. Details, are hard to write, but often very helpful to those starting out (like me). Thanks for making the library. I'll visit the readme and docs. At the moment the only thing that SPI is being used for is the display and touch panel. I may move the touch panel to an alternate SPI, to avoid any bus interaction. The panel may be too small for practical use in the shop, but I won't know until I get deeper in this.

    My thoughts on what I'd like to do is to have sections of the screen update while leaving the rest static. As I understand it, that is graphics 101. I have yet to even design my user interface. Still playing around to get the basics done, which I am nearing completion on. In the UI, I need to select threading or feeding, imperial or metric, and selecting a particular thread to make. So have to make various screens and ways of navigating between them. Should the user select a particular thread, they may be advised to alter settings on the stepper driver. Wish there was a programmatic way to do that, but there's only dip switches there. All in all, this project should be a fun exercise.

  10. #10
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,557
    There are lots of different tricks that you can do.

    If for example you are simply updating one or more fields, you can use the clip rectangle code, where you set the clip around the field being updated and then do an update and only that region will be drawn to.

    I don't remember if the updateScreenAsync had option to only update the dirty region (that area who is bounded by all of the changes. I know the continuous version does not support that.

    Good luck and feel free to ask questions.

  11. #11
    @KurtE have you run the standard graphicstest in DMA mode? Is it any faster? How long would a screen fill take with DMA?

    For the clip rectangle, let me ask these simple questions. The frame buffer is populated as a full screen? But I can update part of the buffer with new information? Then define a clip rectangle and have the update only write the pixels contained within that region be sent to the ILI9431's buffer? What is contained in the frame buffer? Is it pixels and colors? Where can I find out more about this? Thanks. Is there a better thread on the forum to ask about this?

  12. #12
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    @luni, This code stub doesn't seem to work. If I print out c1 and c0, they either are the same, or only differ by one count, independent of the physical encoder shaft RPM. spindleEnc.getValue is not working as I would expect.
    Oh, both variables c0 and c1 need to be int32_t not uint32_t. Sorry for the confusion (never post untested code :-))

    However, I did get it to work using a one shot timer. And now it works with the tft display!
    Great, if it works just stick with it.

    It is not apparent if I am losing any counts. How can I check for this?
    • Take a second Teensy and upload one of th EncSim binaries from here: https://github.com/luni64/EncSim/tre...piled_binaries
    • Start up some Serial Monitor (I recommend TYCommander) and connect to the EncSim Teensy. You should see the following "GUI" https://github.com/luni64/EncSim#serial-interface
    • Connect pins 0 and 1 of the second teensy instead of your encoder to your board.
    • Tell EncSim to do say 10000 steps (mva 10000) and check if your code detects exactly 10000 steps.
    • Increase the count frequency (e.g. freq 50000) and see how far you can go up with the frequency before you loose steps.



    The HW Quadrature library and this encoder tool have opposite senses of rotation.
    If you want to reverse the count direction, just swap the pin numbers in your call to begin(). Changing this in the library would probably break a lot of code out there...

  13. #13
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    10,557
    Quote Originally Posted by clinker8 View Post
    @KurtE have you run the standard graphicstest in DMA mode? Is it any faster? How long would a screen fill take with DMA?

    For the clip rectangle, let me ask these simple questions. The frame buffer is populated as a full screen? But I can update part of the buffer with new information? Then define a clip rectangle and have the update only write the pixels contained within that region be sent to the ILI9431's buffer? What is contained in the frame buffer? Is it pixels and colors? Where can I find out more about this? Thanks. Is there a better thread on the forum to ask about this?
    Frame buffer is simply an array of memory: 2 bytes per pixel: Think of it like:
    uint16_t readPixel(x, y) { return frame_buffer[y*tft.width() + x];}
    void writePixel(x, y, color) {frame_buffer[y*tft.width() + x] = color;}

    Note: obviously not totally valid c++ but simply address into an array....

    If you set a clip rectangle, those parts outside of the clip rectangle are not touched. This is true with or without Frame buffer. That is you can use clip rectangle and all graphic primitives are constrained to only update that region of the display.

    Speed: The time to update all of the pixels on the screen is more or less the same regardless of how you do it (Within this library or ili9341_t3). That is the time is dictated by how long does it take SPI to transfer N pixels to the screen at some specified transfer speed. That is: fillScreen, fillRect whole screen, writeRect whole screen, updateScreen, updateScreenAsync all take so much time for the data to be written over SPI, regardless if DMA or our code that transfers the data directly into the SPI transfer queue.

    However frame buffer - can speed things up and make it easier to write your code to for example not flash: That is if your code is going to update lets say a region of the screen,
    for some textual output. If your code does it like: fillRect(..., background_color), ... draw the text), you will run into the pixels being drawn maybe multiple times, so that causes it to go slower, plus drawing the text, requires more output to the display to specify where pixels or rectangle of pixels go... So again more output. Plus on T4.x we have to wait until SPI has transferred everything before changing state of DC (Data/command) pin, so again slow down:
    Writing pixels/rectangles you need to output something like <ROW> Y1 Y2 <COL> X1 X1 <Fill mem> data to fill this region
    where the stuff in <> are commands and other part is data. We can at times short hand this, where if the x's are the same as the last don't need to output that part, ditto for Ys...

    Where DMA makes a difference, is not on how long does it take for the screen to update, but instead how much of this time, is your program held up. That is with the updateScreenAsync, the code outputs the start of the Output, that is it outputs the Row/Col stuff, and then does the rest DMA. And then your code is free to go do do other things like look at the encoders or ??? And only when you need to again change the screen you could check to see if the last output completed or not...

  14. #14
    @luni, I downloaded the binary for Teensy 4.1. My Teensy loader said the hex file was unreadable. I check permissions on the hex file and it seemed ok. Enabled gHex and was able to read the hex file. Attempted to load the hex file and it would not program the Teensy 4.1. The red LED on the Teensy showed, but never turned off. Basically hung. Perhaps I am using the Teensy programming tool incorrectly. I opened the hex file and then pressed the button on the Teensy. I got a window to pop up. The title of the window stated, "File Error". The body of the window says, " Unable to program Teensy, because the file is not readable. File: SerialControl_T41.hex. Folder: /home/me/Apps/ELS/ELS_docs "

    Clicked ok. Teensy is still in programming mode (red LED is on). Tried a new download, same result.

  15. #15
    @KurtE, thanks for the explanation, very helpful. Gives me a better understanding of the "bigger picture". I have a lot to learn on this front, but this gives me some of the basics, which I was missing.

  16. #16
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Quote Originally Posted by clinker8 View Post
    @luni, I downloaded the binary for Teensy 4.1. My Teensy loader said the hex file was unreadable. I check permissions on the hex file and it seemed ok. Enabled gHex and was able to read the hex file. Attempted to load the hex file and it would not program the Teensy 4.1. The red LED on the Teensy showed, but never turned off. Basically hung. Perhaps I am using the Teensy programming tool incorrectly. I opened the hex file and then pressed the button on the Teensy. I got a window to pop up. The title of the window stated, "File Error". The body of the window says, " Unable to program Teensy, because the file is not readable. File: SerialControl_T41.hex. Folder: /home/me/Apps/ELS/ELS_docs "

    Clicked ok. Teensy is still in programming mode (red LED is on). Tried a new download, same result.
    I can reproduce that. Looks like the binary has some issues. Can you try the attached file? The procedure you described is perfectly OK.
    Attached Files Attached Files

  17. #17
    Quote Originally Posted by luni View Post
    I can reproduce that. Looks like the binary has some issues. Can you try the attached file? The procedure you described is perfectly OK.
    This file downloaded and once extracted was able to be programmed. The original file on github downloaded as several MB, this hex file is 280KB. I will give it a try!

  18. #18
    @luni, I installed (built) TyCommander and tried EncSim out. Got it to work. I can get it to work up to freq = 14000. After that, my stepper can't follow reliably. Don't know if that is because of acceleration rates from a dead stop or other causes. Is there a way to set accel and decel parameters in EncSim? I have had the stepper follow at freq 17000, but not always. (249 RPM)

    It looks like my program might be resetting due to the overrun, but I am not sure. All I know is I have a print statement that is only found in setup and I see the message. At other times my program dies rather ungracefully. Since there's no major error checking besides checking for missing a count, guess I have a lot more defensive code to put in and maybe even some debug lights.

  19. #19
    I don't loose counts, at 20 KHz, but my stepper can't follow. At 20K counts/second my stepper is going at 15994 microsteps/sec, so the stepper can't start reliably from rest at this pulse rate. If EncSim had an accel ramp to frequency and decel to zero (for positioning) then I think my setup could follow. I'm encouraged, however with what I am seeing.

  20. #20
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    @luni, I installed (built) TyCommander and tried EncSim out. Got it to work. I can get it to work up to freq = 14000. After that, my stepper can't follow reliably.
    I thought you are interested if the spindle encoder code looses counts? So the stepper shouldn't be an issue for the test right? Just check if the encSim count equals the spindle counts your program detects.

    Don't know if that is because of acceleration rates from a dead stop or other causes. Is there a way to set accel and decel parameters in EncSim? I have had the stepper follow at freq 17000, but not always. (249 RPM)
    Might be and will of course depend on the ratio of the spindle count frequency to the motor step frequency (i.e. the thread pitch). Max start frequency of a stepper depends on a lot of things (motor mass, driver supply voltage, load etc) the motor datasheet should give you some answers.

    There is no acceleration function in EncSim but you can change the frequency manually while it runs if that helps. In real life your spindle inertia will probably quite high and prevent it from accelerating so fast that your stepper can't follow.

    It looks like my program might be resetting due to the overrun, but I am not sure. All I know is I have a print statement that is only found in setup and I see the message. At other times my program dies rather ungracefully. Since there's no major error checking besides checking for missing a count, guess I have a lot more defensive code to put in and maybe even some debug lights.
    Sounds like a bug :-) Difficult to judge without seeing your program. IMHO one of those cheap (~10USD) logic analyzers (e.g. https://www.amazon.de/AZDelivery-%E2...ps%2C87&sr=8-5) is super helpful for debugging.

  21. #21
    Of course it is a bug . I am running the stepper at 6 TPI, (4.23 mm pitch) which has the highest N/D ratio 0.781. Stress test! Rather see the SW break on my comfortable desk, than down in the shop. At least initially! This little stepper (NEMA-11) is not representative of the NEMA-24 4Nm closed loop stepper I will get. But it helps me better understand the control issues. Just tested at freq 100000, for 20000 steps and no count errors for several cycles. And at freq 200000, 5us period, still follows the counts, for 20000 counts. But it fails at 200,000 counts. Not worried at this point. I will find the bugs...

    Is there a way to set the counter value back to zero (for testing) during run time? I don't understand the syntax of spindleEnc.setValue. How to set the spindle encoder count back to zero using this command? I'm sure it is a C or C++ misunderstanding on my part.

  22. #22
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    I don't understand the syntax of spindleEnc.setValue. How to set the spindle encoder count back to zero using this command?
    There is not much syntax to understand. A simple "spindleEnc.setValue(0);" should reset the counter. What exactly doesn't work?

  23. #23
    @luni, what you showed me works! I didn't understand how to use the command from the header file - ie. I'm not a very proficient C/C++ programmer.

    Have an unusual problem showing up. Occasionally, my program is resetting itself. I put in a serial print of the pitch parameters in set up. I used EncSim to generate 20000 steps at 20KHz. My program, using the SpindleEncoder worked up to 18651 steps. Then it appears the program re-entered setup. I don't know how to do that programmatically, I'm guessing something got clobbered, but I have no idea what. I think I will disable out my tft display and see if it is related to that.

    A different question, what does Integrate to Arduino do in TyCommander? I'm hesitant to click that button, without knowing what it does! Going to the website doesn't show what it does either.

  24. #24
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Feel free to post your program or a link to it for a review. My experience is that you can stare for days at some code and don't find a bug while someone else with fresh eyes might see it in minutes.

    A different question, what does Integrate to Arduino do in TyCommander? I'm hesitant to click that button, without knowing what it does! Going to the website doesn't show what it does either.
    It will use TyCommander for uploads. You can simply undo the integration with a click. So, nothing to fear. I personally only use TyCommander since it integrates a perfect Serial monitor, can handle more than one connected board, shows a lot of useful information etc. I don't use the Arduino IDE much, so having a SerMon integrated to the uploader is super useful for me.

  25. #25
    @luni, sorry to keep bothering you. In your Encoder library there is a member that is an error callback. I keep getting odd resets at certain speeds, where the count value stops updating. How could one use this error callback? I have eliminated any SPI transactions, (display) I am left with only TeensyTimerTool and EncoderTool library calls in my program, so I would like to check if the Encoder is dying. Could you supply a simple code example of its use?
    Think a #define USE_ERROR_CALLBACKS is required, but I don't see an example of the use of error callbacks, nor what really to check for. Does your Encoder library allow abs(delta)>1? What happens if that is true?

Posting Permissions

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