Fast output switching

Hello,

I am trying to make a program that switches 3 pins in a way pictured in attachment.

What I have done already is setting a new hardware timer at a start of each pulse for the next pulse. Everything works fine with longer pulses, but there some jitter with pulses under 1 microsecond. I will attach my program later.

I wanted to ask if there is a way to use few timers instead of one, and preset them before period starts or any other suggestions are welcome.

PIN_Switching.png

vilius09:
I am trying to make a program that switches 3 pins in a way pictured in attachment.

So what timing are you after? And more important, why?

vilius09:
What I have done already is setting a new hardware timer

Where did you buy that one? My Pro Mini's just have three and I can't add a new one. Or should I just ignore the word new? :wink:

vilius09:
Everything works fine with longer pulses, but there some jitter with pulses under 1 microsecond.

What micro are we talking about? us range of timing is getting pretty close to what a Uno can do...

vilius09:
I will attach my program later.

Then why bother posting a code related question already?????

vilius09:
I wanted to ask if there is a way to use few timers instead of one,

Fewer timers then one????

Have a look at Several Things at a Time. The same technique can also be used with micros()

...R

So this is how I now do this task:

ISR(TIMER2_OVF_vect) {
  /* Reload the timer */
  TCNT2 = tcnt2;
  TCCR2B = tccrb2;

  switch (bo) {
    case 0:
      sbi(PORTB, 3);//pin11
      cbi(PORTB, 2); //pin10
      cbi(PORTD, 3);//pin3
      break;
    case 1:
      cbi(PORTB, 3);//pin11
      sbi(PORTD, 3); //pin3
      cbi(PORTB, 2); //pin10
      break;
    case 2:
      sbi(PORTB, 2);//pin10
      cbi(PORTD, 3);//pin3
      cbi(PORTB, 3);//pin11
      bo = -1;
      i++;
      if (i == imax2) {
        s = s + 1;
        i = 0;
        if (s == 7)
        {
          s = 1;
        }
        switch (s) {
          case 1:
            sbi(PORTD, 4);//pin4
            cbi(PORTB, 1);
            break;
          case 2:
            sbi(PORTD, 5);//pin5
            cbi(PORTD, 4);
            break;
          case 3:
            sbi(PORTD, 6);//pin6
            cbi(PORTD, 5);
            break;
          case 4:
            sbi(PORTD, 7);//pin7
            cbi(PORTD, 6);
            break;
          case 5:
            sbi(PORTB, 0);//pin8
            cbi(PORTD, 7);
            break;
          case 6:
            sbi(PORTB, 1);//pin9
            cbi(PORTB, 0);
            break;

        }
      }
      break;
  }

  bo = bo + 1;

  if (taisr[i] == 256 and bo == 0) {
    bo = bo + 1;
  }

  if (tbisr[i] == 256 and bo == 1) {
    bo = bo + 1;
  }

  if (bo == 0) {
    tcnt2 = taisr[i];
    tccrb2 = tar[i];
  }
  else if (bo == 1) {
    tcnt2 = tbisr[i];
    tccrb2 = tbr[i];
  }
  else
  {
    tcnt2 = t0isr[i];
    tccrb2 = t0r[i];
  }
}

I have an arrays with calculated prescalers and overflows which I set at the start of every pulse. Shortest pulse is 0.5 us long and I guess arduino Uno does not keep up with calculations. Any suggestions on optimizing code are welcome.

vilius09:
So this is how I now do this task:
...........
Any suggestions on optimizing code are welcome.

Glad to hear it is working.

Without a detailed english explanation of what all the registers are being used for it would take me far too long to figure out what your program does.

...R

Well it does not work as it should. Whole cycle that should end in 100 us, ends in between 120 and 130 us.

Added some explanations.

ISR(TIMER2_OVF_vect) {
  /* Reload the timer */
  TCNT2 = tcnt2;//register for overflow value
  TCCR2B = tccrb2;//register for prescaler value

vilius09:
Everything works fine with longer pulses, but there some jitter with pulses under 1 microsecond.

The Arduino UNO can only do 16 instruction cycles per microsecond. I suspect your ISR executes more than 16 instruction cycles so it can't complete in time to interrupt within a microsecond.
There may be a way to use Timer1 to generate two of the pulses using the OCR pins and some external logic hardware to generate the third pulse. The diagram doesn't specify any pulse length ranges or desired precision so it's hard to determine if your goal is possible.

The shortest pulse is 0.5 microsecond.

vilius09:
Added some explanations.

That is not nearly enough for me. I would like to see a narrative that talks me through the entire program. This section does X when Y happens and this section does M when N happens etc.

Writing the narrative might also help you to spot a problem.

...R

vilius09:
The shortest pulse is 0.5 microsecond.

I don't think an interrupt can be called and returned within 0.5us, maybe not even a NAKED one.

0.5us is just 8 clock cycles. Your task is achievable on a UNO with careful management of instructions around that 0.5us pulse but if you just want a simple timers and interrupts solution you'll need a faster MCU.

It appears that one of the three signals is high at all times so you only need to generate two and use an NOR gate for the third. Timer1 might be able to generate two of the pulses using PWM. To get 100 uS cycle time you will need 10 kHz PWM.

To get 10 kHz PWM you divide 16 MHz by 10 kHz to get a TOP value of 1600 (give or take one, you have to look up the formula in the datasheet). That gets you 1600 steps of PWM for 1/16th microsecond to 100 microseconds in 16ths of a microsecond. Set the two Output Compare Registers where you want them and use some logic gates to get the three signals you want.