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





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.