Arduino NANO EVERY and Servo and Tone issues

Hi guys.
I just received my new NANO Every.
I had to reinstall the IDE (Win 10) and add the MegaAVR boards to get it to communicate. All OK running the Blink example BUT, when I try to run my NANO v3 sketches I run into multiple issues.

My main ones have to do with the Servo and Tone commands, even after updating the libraries.

Here is the error messages I get:

Tone.cpp.o (symbol from plugin): In function `tone(unsigned char, unsigned int, unsigned long)':

(.text+0x0): multiple definition of `__vector_13'

libraries\Servo\megaavr\Servo.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Arduino Nano Every.

Any help/insight appreciated.

Regards

Gian

Update:

I have also tried to compile and upload using the Online Editor. Exact same issues and errors are reported.

You have an interrupt conflict. I'm not familiar with the processor on your board; look in the datasheet what vector 13 is and take it from there.

There might be alternatives to the libraries that you use or you can hack one of the two libraries; maybe servo2 wiil do the trick.

Hi, thanks for the reply.

I understand the errors and I could try modifying the libraries BUT, I think this should be done officially.

The new NANO boards, and in particular the NANO EVERY, are advertised as drop in replacements for all the existing NANO based projects. I think they should work as advertised.

I can’t believe that everyone in Arduino has missed an incompatibility with such popular libraries like the servo library. Even if they have, the very least I would expect is a very quick fix or at least a mention of such incompatibilities in the product specifications so future buyers are aware.

(deleted)

Hi, this is an existing older Nano project, compiled thousands of times during development. It’s currently working on 60+ robots.

The errors are only reported when compiling for the new NANO EVERY board.

Tried 5 fresh IDE installations in Win10, both from the Windows store and from the Windows 7 and up installer files, even tried the online editor, same errors.

Can someone try to compile a simple sketch using the servo library and the new NANO EVERY board?

(deleted)

Same errors

Which libraries are you using?

The uno wifi rev2 uses the same processor, but it apparently has not generated enough interest to get the libraries updated. Last time I checked FastLED still will not compile on the nano every, and it is a nice board for led strips, with more memory and no special progmem instructions.

Servo and Tone should work fine on the ATmega4809 boards.

Just not at the same time. Both try to use the same timer, so you get a duplicate vector error when you try to use them both, because they both need to use the TCB1 OVF interrupt.

You should be able to go to:
(sketchbook)/Libraries/Servo/src/megaavr/ServoTimers.h

Uncomment:
#define USE_TIMERB2
and comment out
#define USE_TIMERB1
Save, recompile, and all should be well. IIRC the stock megaAVR core's initialization sets up all three timers, so you should be good to go.

I am surprised that Tone and Servo play well with eachother on the nano V3 though - I thought both wanted to use Timer1 on the atmega328p, as that's the only 16-bit timer...

@spycatcher - libraries on different architectures (in this case avr vs megaavr) are not comparable when it gets down to the level of how they use hardware resources; you should know this.

@david_2018 - I don't know about FastLED - but the Adafruit Neopixel library should work for WS2812 since the Uno Wifi Rev.2 and Nano Every are both clocked at 16MHz, and at 16MHz Adafruit Neopixel just calls out to the core libraries to get the PORT output register, and doesn't care that the name of the register is way different (at slower clock speeds, this doesn't work because of how tightly they had to tune the assembly, so it needs some tweaks - I'm planning to get a tweaked version of the Adafruit Neopixel library working on megaAVR at 8, 10, 16, and 20MHz this weekend to integrate into megaTinyCore). Adafruit Neopixel definitely works on the megaavr attiny's at 16MHz without modification.

@DrAzzy, thanks for the input. I know its a timer conflict. I will try your suggestion and report back, for future references.

I forget what that section looks like in the official version of Servo - there may be a #define like TIMER_TO_USE, which is then fed into some #if preprocessor macros on the following lines, and that you would change to 2 instead of 1. You should be able to figure it out when you have the file open.

For what is worth, I got it working with tweaks to the Servo library as per @DrAzzy's instructions. If anyone is interested I can share the fix. Basically, to gain access to the Servo library you have to install the IDE with the Windows installer (the Windows App IDE does not let you alter the library files) and then change the timers used by the Servo megaAVR files, based on which PWM pin you do not want the timer to interfere with.

Thanks @DrAzzy.

Giannos

@DrAzzy I was aware that Adafruit Neopixel would work with the Nano Every. I had even gone to the trouble of attempting to modify it to work with the 20MHz clock frequency, that is when I discovered the clock speed was actually 16MHz.

Here is the code I had modified for 20MHz, it appears to work ok with a string of 10 leds, didn't have more to test it on, and I made no modifications to the 400khz code section, had not gotten around to looking at that part, and have no leds for testing anyway.

// ***********************************************************************
// **************** my code for atmega4809 *******************************
// 20 MHz(ish) AVR --------------------------------------------------------
#elif (F_CPU == 20000000UL)
//#warning "processing for 20MHz clock" F_CPU
#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
  if(is800KHz) {
#endif

    // WS2811 and WS2812 have different hi/lo duty cycles; this is
    // similar but NOT an exact copy of the prior 400-on-8 code.

    // 25 inst. clocks per bit: HHHHHHHxxxxxxLLLLLLLLLLLL
    // ST instructions:         ^      ^     ^        (T=0,7,13)

    volatile uint8_t next, bit;

    hi   = *port |  pinMask;
    lo   = *port & ~pinMask;
    next = lo;
    bit  = 8;

    asm volatile(
     "head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
      "st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
      "sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
       "mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
      "dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T =  7)
      "st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  9)
      "mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T = 10)
      "breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
      "rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 12)
      "nop"                      "\n\t" // 1    nop           (T = 13)
      "st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 17)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 19)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 21)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 23)
      "rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
     "nextbyte20:"               "\n\t" //                    (T = 12)
      "ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 13)
      "st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
      "ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 17)
      "sbiw %[count], 1"         "\n\t" // 2    i--           (T = 19)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 21)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 23)
      "brne head20"              "\n"   // 2    if(i != 0) -> (next byte)
      : [port]  "+e" (port),
        [byte]  "+r" (b),
        [bit]   "+r" (bit),
        [next]  "+r" (next),
        [count] "+w" (i)
      : [ptr]    "e" (ptr),
        [hi]     "r" (hi),
        [lo]     "r" (lo));

#ifdef NEO_KHZ400
  } else { // 400 KHz

    // The 400 KHz clock on 16 MHz MCU is the most 'relaxed' version.

    // 40 inst. clocks per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL
    // ST instructions:         ^       ^           ^         (T=0,8,20)

    volatile uint8_t next, bit;

    hi   = *port |  pinMask;
    lo   = *port & ~pinMask;
    next = lo;
    bit  = 8;

    asm volatile(
     "head40:"                  "\n\t" // Clk  Pseudocode    (T =  0)
      "st   %a[port], %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
      "sbrc %[byte] , 7"        "\n\t" // 1-2  if(b & 128)
       "mov  %[next] , %[hi]"   "\n\t" // 0-1   next = hi    (T =  4)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T =  6)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T =  8)
      "st   %a[port], %[next]"  "\n\t" // 2    PORT = next   (T = 10)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 12)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 14)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 16)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 18)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 20)
      "st   %a[port], %[lo]"    "\n\t" // 2    PORT = lo     (T = 22)
      "nop"                     "\n\t" // 1    nop           (T = 23)
      "mov  %[next] , %[lo]"    "\n\t" // 1    next = lo     (T = 24)
      "dec  %[bit]"             "\n\t" // 1    bit--         (T = 25)
      "breq nextbyte40"         "\n\t" // 1-2  if(bit == 0)
      "rol  %[byte]"            "\n\t" // 1    b <<= 1       (T = 27)
      "nop"                     "\n\t" // 1    nop           (T = 28)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 30)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 32)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 34)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 36)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 38)
      "rjmp head40"             "\n\t" // 2    -> head40 (next bit out)
     "nextbyte40:"              "\n\t" //                    (T = 27)
      "ldi  %[bit]  , 8"        "\n\t" // 1    bit = 8       (T = 28)
      "ld   %[byte] , %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 30)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 32)
      "st   %a[port], %[lo]"    "\n\t" // 2    PORT = lo     (T = 34)
      "rjmp .+0"                "\n\t" // 2    nop nop       (T = 36)
      "sbiw %[count], 1"        "\n\t" // 2    i--           (T = 38)
      "brne head40"             "\n"   // 1-2  if(i != 0) -> (next byte)
      : [port]  "+e" (port),
        [byte]  "+r" (b),
        [bit]   "+r" (bit),
        [next]  "+r" (next),
        [count] "+w" (i)
      : [ptr]    "e" (ptr),
        [hi]     "r" (hi),
        [lo]     "r" (lo));
  }
#endif // NEO_KHZ400

// ***********************************************************************
// ***********************************************************************

GianNos:
For what is worth, I got it working with tweaks to the Servo library as per @DrAzzy's instructions. If anyone is interested I can share the fix. Basically, to gain access to the Servo library you have to install the IDE with the Windows installer (the Windows App IDE does not let you alter the library files) and then change the timers used by the Servo megaAVR files, based on which PWM pin you do not want the timer to interfere with.

Thanks @DrAzzy.

Giannos

Changing the timer should be easy, in the Servo library the file src\megaavr\ServoTimers.h has a define statement for which timer to use, followed by define statements for the other available timers that have been commented out. Just comment out the currently used timer and uncomment the one you want to use.