Menu

ServoIn not working for me on Arduino Leonardo

Bugs
Anonymous
2013-04-05
2013-04-08
  • Anonymous

    Anonymous - 2013-04-05

    Hi,

    I was so happy to find your lib that I tried it out. I have to add that I am an arduino newbie and don't know much about AVRs. I'm just a "stupid" electrical engineer.

    With a servotester as an input connected to Pin 9, I used the ServoIn Example and tried to have an LED flicker on pin 12 depending on the setting of the servo.

    So I check the value of g_values[1] (for pin 9) and that is always 0.

    Could this depend on the Leonardo not being able to generate the right interrupts? Somehow the docu suggests that int.0 in Leonardo works on pin 2 only:

    Quote:
    Most Arduino boards have two external interrupts: numbers 0 (on digital pin 2)
    and 1 (on digital pin 3). The table below shows the available interrupt pins
    on various boards.


    Board int.0 int.1 int.2 int.3 int.4 int.5
    Uno, Ethernet 2 3
    Mega2560 2 3 21 20 19 18
    Leonardo 3 2 0 1

    Can you point me the right direction?

    Thanks for your help
    Jocki

     

    Last edit: dvdouden 2013-04-08
    • dvdouden

      dvdouden - 2013-04-08

      Hi,

      Thanks for your interest in ArduinoRCLib! I only have an Arduino Uno/Nano and Mega, so I never tested the lib on the Leonardo. The lib and examples have been written to work for ATmega168/328 based devices, the Leonardo uses an ATmega32U4 which is slightly different, most importantly the pin mapping of the Leonardo is different. On the Uno pins 8-11 map to PB0-3, on the Leonardo that's PB4-7.

      Fortunately though, pin change interrupts on the Uno are the same as on the Leonardo for port B pins. (By the way, I use pin change interrupts instead of external interrupts, since the ATmega328 only has 2 pins for that, but can handle pin change interrupts on any pin.)

      So instead of PCINT0-3, the example should use PCINT4-7, which maps to digital pins 8-11 on the Leonardo.

      Here is an untested modified version of the example which should work for the Leonardo. Good luck!

      #include <ServoIn.h>
      #include <Timer1.h>
      
      #define SERVOS 4
      
      uint16_t g_values[SERVOS];                    // output buffer for ServoIn
      uint8_t  g_workIn[SERVOIN_WORK_SIZE(SERVOS)]; // we need to have a work buffer for the ServoIn class
      
      rc::ServoIn g_ServoIn(g_values, g_workIn, SERVOS);
      
      void setup()
      {
          // Initialize timer1, this is required for all features that use Timer1
          // (PPMIn/PPMOut/ServoIn/ServoOut)
          rc::Timer1::init();
      
          // We use pin 8-11 as Servo input pins
          pinMode(8, INPUT);
          pinMode(9, INPUT);
          pinMode(10, INPUT);
          pinMode(11, INPUT);
      
          // We use pin change interrupts to detect changes in the signal
          // If you're unfamiliar with how this works, please look up some
          // article or tutorial on the subject.
      
          // only allow pin change interrupts for PB4-7 (digital pins 8-11)
          PCMSK0 = (1 << PCINT4) | (1 << PCINT5) | (1 << PCINT6) | (1 << PCINT7);
      
          // enable pin change interrupt 0
          PCICR = (1 << PCIE0);
      
          // start listening
          g_ServoIn.start();
      }
      
      void loop()
      {
          // update incoming values
          g_ServoIn.update();
      
          // handle servo values here, stored in g_values
      }
      
      // Interrupt handling code below, this needs cleaning
      
      static uint8_t lastB = 0;
      
      // Pin change port 0 interrupt
      ISR(PCINT0_vect)
      {
          // we need to call the ServoIn ISR here, keep code in the ISR to a minimum!
          uint8_t newB = PINB;
          uint8_t chgB = newB ^ lastB; // bitwise XOR will set all bits that have changed
          lastB = newB;
      
          // has any of the pins changed?
          if (chgB)
          {
              // find out which pin has changed
              if (chgB & _BV(PINB4))
              {
                  g_ServoIn.pinChanged(0, newB & _BV(PINB4));
              }
              if (chgB & _BV(PINB5))
              {
                  g_ServoIn.pinChanged(1, newB & _BV(PINB5));
              }
              if (chgB & _BV(PINB6))
              {
                  g_ServoIn.pinChanged(2, newB & _BV(PINB6));
              }
              if (chgB & _BV(PINB7))
              {
                  g_ServoIn.pinChanged(3, newB & _BV(PINB7));
              }
          }
      }
      
       
  • dvdouden

    dvdouden - 2013-04-08

    Okay, so plugging in your 12V battery backwards is a bad idea, that kills voltage regulators. Plugging it in the correct way after that is also a bad idea since a burned voltage regulator will supply 12V instead of 5V. In other words, my Arduino Uno is now in the garbage bin.

    In other news: I've just ordered an Arduino Leonardo to replace it, so compatibility with that board has just been added to my to-do list.

     
    • Anonymous

      Anonymous - 2013-04-08

      I'm sorry to hear that you burnt your device :-(

      Something similar happened to my speed controller just last week, so I can sympathise.

      Thanks for your updated example, I was just reading about all the interrupt stuff but did not get to the point where the two devices are different. Now, that solves the issue! If you don't hear from me, I'm set and everything works.... :-)

      Good luck with the Leonardo!

       
      • dvdouden

        dvdouden - 2013-04-08

        You'd think one would learn after burning one or two devices, but noooo ;-)

         

Anonymous
Anonymous

Add attachments
Cancel





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.