Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 22 of 22

Thread: EncoderTool Problems

  1. #1
    Member fdaniels's Avatar
    Join Date
    Oct 2020
    Location
    Ostwestfalen, Germany
    Posts
    93

    EncoderTool Problems

    I just wanted to start a new Sketch, copying definitions for Hardware and Variables from an older Sketch and - voila - it doesnt work.

    It boils down to this:

    Code:
    #include "EncoderTool.h"
    using namespace EncoderTool;
    
    Encoder encoder;
    
    int value=0;
    
    void setup() {
      // put your setup code here, to run once:
      encoder.begin(14,15);
      encoder.setValue(0);
    }
    
    void loop() {
       //put your main code here, to run repeatedly:
       value = encoder.getValue();
    }
    Gives this Error:


    Arduino: 1.8.13 (Windows 10), TD: 1.53, Board: "Teensy 3.2 / 3.1, Serial, 96 MHz (overclock), Faster, US English"

    c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/lib/armv7e-m\libc.a(lib_a-writer.o): In function `_write_r':

    writer.c.text._write_r+0x12): undefined reference to `_write'

    collect2.exe: error: ld returned 1 exit status

    Error compiling for board Teensy 3.2 / 3.1.


    while changing " value = encoder.getValue();" to "Serial.println( encoder.getValue());" like below compiles fine.

    Code:
    #include "EncoderTool.h"
    using namespace EncoderTool;
    
    Encoder encoder;
    
    int value=0;
    
    void setup() {
      // put your setup code here, to run once:
      encoder.begin(14,15);
      encoder.setValue(0);
    }
    
    void loop() {
       //put your main code here, to run repeatedly:
      Serial.println( encoder.getValue());
    }
    Any Ideas what i am doing wrong? Im a bit puzzled as i used these Lines in allmost all sketches before and all of these compile just fine.

  2. #2
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    Your are doing nothing wrong. I can reproduce it but it is super weird. Something seems to try to use some c-library function which writes to stdout. Those functions need '_write' defined to do this. But, as usual in embedded systems _write is not defined. I'll need to dig into this in more detail.

    Following quick workarounds:

    • As soon as you use Serial.println("something") the error goes away. (this is probably the reason why nobody noticed the problem so far)
    • The T4.1 core works without problem (need to look for the differences, maybe the T4.1 core lib defines '_write' somewhere
    • If you disable std::function callbacks (uncomment line 4 in the config file) it works



    Code:
    void loop() {
       val = encoder.getValue();
       Serial.println("weird");      // errror if you uncomment this line
    }

  3. #3
    Member fdaniels's Avatar
    Join Date
    Oct 2020
    Location
    Ostwestfalen, Germany
    Posts
    93
    Puh - i thought i am to dumb to understand.....

    I can confirm, first calling a Serial.println("Irgendwas"); is a workaround. I got a bit crazy, because i just copied + pasted these lines from another Sketch and it works in the original Sketch flawless. If you like i can send you the whole Code as Mail, so you can have a look (its ab "bit" untidy and looong, so im not too keen to post it here).

    Just checked:
    Code:
    #include "EncoderTool.h"
    using namespace EncoderTool;
    
    Encoder encoder;
    
    int value=0;
    
    void setup() {
      // put your setup code here, to run once:
      encoder.begin(14,15);
      encoder.setValue(0);
     
    }
    
    void loop() {
       //put your main code here, to run repeatedly:
       value= encoder.getValue();
        
    }
    compiles fine for Teensy LC + 4.0

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    Does the other code print something to serial?

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,727
    Both Teensy 3 & 4 define _write() in Print.cpp.

    My best guess is something we're doing somewhere in the core library is always linking in the Print class, and nobody has cared because we have megabytes of flash on Teensy 4. And Teensy 4 has only existed for a little over 1 year, so there hasn't been a lot of time for anyone to really worry minor issues where the only consequence is extra flash used.

    But Teensy LC has much less memory, and has been around for several years. Quite a lot of work as gone into making sure we don't accidentally force unneeded code to get always linked in.

    The really mysterious part (to me) is why would #include <functional> and use of the std:function templates result in something wanting to call _write() ?

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,727
    I'm a little worried about this, because on my long & low-priority TODO list is converting attachInterrupt() and EventResponder to use std::function. Maybe not such a great idea afterall?

  7. #7
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    Both Teensy 3 & 4 define _write() in Print.cpp.
    Yes, I've seen this. I also saw this over the part in setup.c where you define the other syscalls.
    Code:
    // syscall functions need to be in the same C file as the entry point "ResetVector"
    // otherwise the linker will discard them in some cases.
    
    #include <errno.h>
    
    // from the linker script
    extern unsigned long _heap_start;
    extern unsigned long _heap_end;
    //.....
    I wonder if moving the _write definition would fix it.

  8. #8
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    I wonder if moving the _write definition would fix it.
    If I move the definiton of _write from print.cpp to mk20dx12.c above the definition of _read, it works:
    Code:
    __attribute__((weak))
    int _write(int file, char *ptr, int len)
    {
    	//((class Print *)file)->write((uint8_t *)ptr, len);
    	//return len;
    	return 0;
    }
    Alternatively, if you put this
    Code:
    extern "C" {
      int _write( int handle, char *buf, int count )
      {
          return Serial.write(buf, count);
      }
    }
    in some c++ file it gets linked and you can use the standard printf to print on Serial (if this is desirable at all).


    I'm a little worried about this, because on my long & low-priority TODO list is converting attachInterrupt() and EventResponder to use std::function. Maybe not such a great idea afterall?
    I'm using it all the time, never had issues with it since you fixed the linker script and the link sequence in 1.53
    Last edited by luni; 12-21-2020 at 03:02 PM.

  9. #9
    Member fdaniels's Avatar
    Join Date
    Oct 2020
    Location
    Ostwestfalen, Germany
    Posts
    93
    Quote Originally Posted by luni View Post
    Does the other code print something to serial?
    Nope, heres a snippet of the Code from a Sketch where it works:

    Code:
    pinMode(stopLEDpin, OUTPUT);
    
    
      analogWriteResolution(12);
    
      encoder.begin(encoderA,encoderB);  // A=0, B=1
      encoder.setValue(0);
      encOldValue = encoder.getValue(); // get current value
    
       // SETUP ACCUMULATOR TIMER
      //stepTimer.begin(updateOutputs, 250); 
    
      // SETUP BUTTON INTERRUPT
      //attachInterrupt(digitalPinToInterrupt(runButtonPin), runButtonISR, LOW);
    
      //TEMPOARRAY UPDATE
      recalculateTempo();
      
      // SETUP SERIAL MONITOR 
      Serial.begin(9600); 
      displaySplashScreen();
    So im starting the Encoder before even starting Serial, and it works there flawless.

  10. #10
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    @fdaniels: I uploaded a fixed version which works here. Can you give it a try? (it implements the missing _write() which is a bit rude but works)

    @Paul:
    I'm a little worried about this, because on my long & low-priority TODO list is converting attachInterrupt() and EventResponder to use std::function. Maybe not such a great idea afterall?
    So was I. To test it I placed a while(1){} in _write() which would effectively halt the processor, which did not happen... Looks like it never really calls _write, it just needs it to keep the linker happy.

    BTW: I have an implementation of attachInterrupt() using std::function instead of the plain function pointer callback. In case you get bored and want to play around: https://github.com/luni64/TeensyHelpers
    Last edited by luni; 12-21-2020 at 03:08 PM.

  11. #11
    Member fdaniels's Avatar
    Join Date
    Oct 2020
    Location
    Ostwestfalen, Germany
    Posts
    93
    Quote Originally Posted by luni View Post
    @fdaniels: I uploaded a fixed version which works here. Can you give it a try? (it implements the missing _write() which is a bit rude but works)
    Adding EncoderTool-master from today to my /Dokumente/Arduino/Libraries folder in addition to EncoderTool-2.2.1 now compiles the Code in question:
    Code:
    #include "EncoderTool.h"
    using namespace EncoderTool;
    
    Encoder encoder;
    
    int value=0;
    
    void setup() {
      // put your setup code here, to run once:
      encoder.begin(14,15);
      encoder.setValue(0);
     
     
     
    }
    
    void loop() {
       //put your main code here, to run repeatedly:
      //Serial.println( encoder.getValue());
      value=encoder.getValue();
      
    }
    gives this:
    Sketch uses 79376 bytes (30%) of program storage space. Maximum is 262144 bytes.
    Global variables use 5556 bytes (8%) of dynamic memory, leaving 59980 bytes for local variables. Maximum is 65536 bytes.


    Also, it compiles the old sketches flawless.

    As far as my problem is concerned i'd say "problem solved" but i hope i didnt find something more worrying...
    If i can be of any help, let me know.

    Many thanks for diving into this!!!!

  12. #12
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    Great. Let me know if you find something else.

    i hope i didnt find something more worrying...
    No, just some things unthought of so far. Would be boring if everything just worked :-).

  13. #13
    Member fdaniels's Avatar
    Join Date
    Oct 2020
    Location
    Ostwestfalen, Germany
    Posts
    93
    Next Problem: the new Library doesnt compile older Sketches properly anymore for the LC:

    Code:
    #include "EncoderTool.h"
    using namespace EncoderTool;
    
    Encoder encoder;
    
    int value=0;
    
    void setup() {
      // put your setup code here, to run once:
      encoder.begin(11,12);
       encoder.setValue(0);
      
      //pinMode(14, INPUT_PULLUP);
     
    }
    
    void loop() {
       //put your main code here, to run repeatedly:
      //Serial.println( encoder.getValue());
      value=encoder.getValue();
      Serial.println(value);
    
      //if (digitalRead(14)==1){Serial.println("BUTTON");}
      
    }
    produces this:

    Arduino: 1.8.13 (Windows 10), TD: 1.53, Board: "Teensy LC, Serial, 48 MHz, Smallest Code, US English"

    C:\Users\danie\Documents\Arduino\libraries\Encoder Tool-master\src\EncoderBase.cpp:196:1: error: expected declaration before '}' token

    }

    ^

    Multiple libraries were found for "EncoderTool.h"

    Used: C:\Users\danie\Documents\Arduino\libraries\Encoder Tool-master

    Not used: C:\Users\danie\Documents\Arduino\libraries\Encoder Tool-2.2.1

    Error compiling for board Teensy LC.


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


    While exactly the same Code compiles for 3.2...

  14. #14
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    Ups, can you move the #endif after the closing bracket in EncoderBase.cpp (line 196). The #endif should be the last statement in the file. I need to leave right now, I'll fix it later today

  15. #15
    Member fdaniels's Avatar
    Join Date
    Oct 2020
    Location
    Ostwestfalen, Germany
    Posts
    93
    Thanks for your superquick response!!
    Will try this asap later - ill have to leave as well getting some things we missed yesterday for xMas.... ;-)

  16. #16
    Senior Member manicksan's Avatar
    Join Date
    Jun 2020
    Location
    Sweden
    Posts
    221
    79k for that simple sketch
    What is going on there?

  17. #17
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    79k for that simple sketch
    What is going on there?
    For memory challenged boards you can switch off the std::function support in config.h.

  18. #18
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    Will try this asap later - ill have to leave as well getting some things we missed yesterday for xMas.... ;-)
    Yes, wife and daughter made me go in the forest to cut a tree :-)

  19. #19
    Member fdaniels's Avatar
    Join Date
    Oct 2020
    Location
    Ostwestfalen, Germany
    Posts
    93
    Picture please!

  20. #20
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    Picture please!
    Well, its more like a baby tree and I had a hard time mounting it but it is a self cut tree after all

    Click image for larger version. 

Name:	IMG_20201223_145653.jpg 
Views:	13 
Size:	128.3 KB 
ID:	22926

  21. #21
    Member fdaniels's Avatar
    Join Date
    Oct 2020
    Location
    Ostwestfalen, Germany
    Posts
    93
    Man, this one is beautiful!
    Have a very nice xMas, all the best for you and your loved ones!

  22. #22
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,365
    I uploaded a fix for the wrong conditional to the master branch of the lib.

    BTW: Does anybody know of a working unit test framework for embedded projects? The growing number of boards makes proper testing of libraries a nightmare. Something more automated would be a real timesaver.

Posting Permissions

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