Menu

PPMOut.h change PPM Output Pin

Features
Anonymous
2012-06-24
2012-10-30
  • Anonymous

    Anonymous - 2012-06-24

    At the moment only PIN 9 an 10 can be used as outgoing PIN

    Is there a way to modify the g_PPMOut.start(); function to hand over the out pin? For example: g_PPMOut.start(11);

    I already tried to change the function but I am not sure because the "p_a" value is also used for the following line: c::Timer1::setToggle(true, p_a);

     
    • dvdouden

      dvdouden - 2012-10-29

      Sorry for the really late reply, I'm answering this in case someone ever has the same question and stumbles upon this :)

      If I ever find the time I will add this to the library...

      I recently got the same question by email, so here's my copy/paste answer:

      PPM output works best with pins 9-10 since they're directly tied to
      Timer 1. As timer 1 generates an interrupt, the hardware will
      automatically toggle the value on either pin 9 or 10. However, it's
      not that hard to make PPMOut use a different pin, you just need to
      toggle the pin you want manually in the interrupt handler. For this
      you need to make some changes to PPMOut.cpp:
      -In PPMOut::start(), change uint8_t pin = p_a ? 9 : 10; to the pin
      number you want and remove this line: rc::Timer1::setToggle(true,
      p_a);
      -In PPMOut::isr(), toggle your output pin on the first line of that function.

      so, to summarize, you'll get something like this:

      void PPMOut::start(bool p_a, bool p_invert)
      {
      // stop timer 1
      rc::Timer1::stop();
      
          // Fill channelTimings buffer with data from channels buffer
          update();
      
          // Fill timings buffer with data from channelTimings buffer     (set up a
      
      complete PPM frame)
      updateTimings();
      
          uint8_t pin = <SOME PIN HERE>; // fill this in yourself
          m_timingPos = p_invert ? 0 : 1;
      
          pinMode(pin, OUTPUT);
      
          // First disable the output compare match A interrupt
          rc::Timer1::setCompareMatch(false, true);
      
          // set compare value
          OCR1A = TCNT1 + m_timings[p_invert ? m_timingCount - 1 : 0];
      
          // enable timer output compare match A interrupts
          rc::Timer1::setCompareMatch(true, true,     PPMOut::handleInterrupt);
      
          // start the timer
          rc::Timer1::start();
      
      }
      

      and

      void PPMOut::isr()
      {
      // fill this in yourself
      
          // set the compare register with the next value
          OCR1A += m_timings[m_timingPos];
      
          // update position
          ++m_timingPos;
          if (m_timingPos >= m_timingCount)
          {
                  m_timingPos = 0;
      
                  // we're at the end of frame here, so there's plenty of time to update
                  updateTimings();
          }
      
      }
      

      It is possible to toggle an output pin by writing to its input register

      uint8_t mask = digitalPinToBitMask();
      uint8_t port = digitalPinToPort();
      volatile uint8_t out = portInputRegister(port);
      out |= mask;
      

      You can simply store the mask and out variable somewhere else (as
      member variable of PPMOut for example) and just do *out |= mask in the
      isr function. This will keep the amount of code (and time spent) in
      the isr to a minimum and ensure the timing precision you want. I
      didn't have a chance to test this code since I accidentally melted my
      Arduino some time ago (short circuit). It should work though, the same
      principle is used for generating a servo signal.

       

      Last edit: dvdouden 2012-10-29
      • dvdouden

        dvdouden - 2012-10-30

        Added in [r84], still needs testing

         

        Related

        Commit: [r84]

Anonymous
Anonymous

Add attachments
Cancel