5us delay when shifting digital OUTPUT levels

as the subject line suggests:

When attempting output digital data at high speeds I have noticed an anomaly, the pulse width randomly increases or decreases by 5us.

This occurs regardless of the code used to modify the pin levels. (digitalWrite, directly modifying the entire PORT register, using bitWrite or bitSet on the port register). Thus i am forced to conclude the delay is occurring at a hardware level between the port register and the transistors controlling the IO pins.

Upon examining the signals sent by the Serial library over Tx there appears to be a 10us shift that appears. this is extremely puzzling since the computer is still able to receive the data even at 115200 baud (pulse width 8.7us).

All of this data has been recorded independently of the 3us delay between the void loop() ending and restarting.

Any hints on enabling High speed communication over the digital pins would be appreciated. this 5us delay in level shifting interferes even at 9600baud.

  1. Post your code, otherwise we don't know exactly what you are doing..

  2. If the 5us delay is happening only occasionally (about every 1ms), then it could be caused by the timer interrupt service routine.

This code is a 5 channel bi-directional multiplexer that takes 5 inputs from on arduino and outputs it on a second arduino.
The intention is to place fibre optic lines on Tx and Rx and use the two arduino's to transmit the 5 RS-232 channels to and from devices mounted on a telescope. (hence the need for high speed, everything is very time critical).

The effect i am referring to can be observed at the output channels of the arduino's, or by simply switching the digital pins on a single arduino on and off at >50kHz and looking at the signal with an oscilloscope.

byte sendByte = 0;
byte receiveByte=0;
byte temp;

void setup() {
        Serial.begin(115200);     // opens serial port, sets data rate to 115200 bps

for(int p = 3; p <= 7; p++){
  pinMode(p, INPUT);}
for(int p = 8; p <= 12; p++){
  pinMode(p, OUTPUT);}
  
}

void loop() {

  sendByte = PIND>> 3; // read PORTD and shift it 3 bits to the right to drop the readings from pin 0-2.
  
        Serial.write(sendByte);

        // check for data in the serial buffer
        if (Serial.available() > 0) {
                // read the incoming byte:
                receiveByte = Serial.read();

               }
               
          PORTB = receiveByte;
}

Ah, so the data you are outputting has been received from the serial port. In that case, you have not only the timer ISR to consider but also the serial port ISR. Either could account for a delay of about 5us.

aShadow:
When attempting output digital data at high speeds I have noticed an anomaly, the pulse width randomly increases or decreases by 5us.

I'm not surprised - I don't see anything in the code to control the timing of this. I don't know what the final speed will be determined by - is it blocking on the serial write?

By timer ISR you mean interrupt service routine?
Does the Serial communications use an interrupt method?

The interesting thing is the "jitter" as i am calling it is present even with the following code:

void loop() {

          PORTB = B11111111;
delaymicroseconds(10);
PORTB=B00000000;
delaymicroseconds(10);


}

This is how i found the 3us loop repetion delay. the pin is low for 3us longer than it is high.

the signal on the oscilloscope appears to shiver, with the falling or rising edges shifting 5 us so that the high or low pulse would randomly be 15 us instead of 10 and then jump back to normal.

*edit: its not random, i just cant see the pattern since i dunno whats causing it. (seems to occur every 100us or so, but this is not constant).

aShadow:
By timer ISR you mean interrupt service routine?
Does the Serial communications use an interrupt method?

Yes and yes.

aShadow:
The interesting thing is the "jitter" as i am calling it is present even with the following code:

void loop() {

PORTB = B11111111;
delaymicroseconds(10);
PORTB=B00000000;
delaymicroseconds(10);

}




This is how i found the 3us loop repetion delay. the pin is low for 3us longer than it is high.

the signal on the oscilloscope appears to shiver, with the falling or rising edges shifting 5 us so that the high or low pulse would randomly be 15 us instead of 10 and then jump back to normal.

*edit: its not random, i just cant see the pattern since i dunno whats causing it. (seems to occur every 100us or so, but this is not constant).

That would be caused by the timer ISR, which occurs every 1024us. To check that the cause of he jitter is interrupts, if you temporarily add a disable() call then the jitter should go away - but then serial comms and delay() won't work (although delayMicroseconds will still work).

Using fixed delays isn't a good way to achieve that sort of timing resolution IMO. It seems to me you'd be far better off using a hardware timer so that you can generate the output without involving the processor at all. If that's not feasible for some reason then use a timer interrupt to trigger your code to generate the output - but then you will have to deal with contention with the other interrupts handlers.

To do this in the main code would be harder, but I think it would be possible if you put the Arduino runtime library aside and do all the serial I/O and timing yourself, without involving interrupts.

Hi guys, thanks for the helpful hints.
Yes it is definitely being caused by interrupt service routines in the serial library.

So, i need to somehow set up serial comms without using interrupts. o.O

Is that even possible.
The only way i can think of is to sample the Rx pin really fast and just hope i don't miss any bits -_-

Oh yes, the output level shifting delay is actually more like a 60us shift.
The 5us of jitter appears on the Tx line of outgoing serial comms.

Meh, since i am trying to multiplex 5 RS232 lines at 9600 baud, the arduino cannot achieve a sample rate high enough (since the arduino to arduino serial comms would need to be > 115.2kbaud).

Thus i must conclude that this is impossible with a clock frequency of only 16MHz.

Next question. How high can i clock the atmega328 before it explodes? :smiley:
More technically, how much does its heat production increases with increased clock frequency.

Can you compress the data so that you don't need to send as much between the Arduinos?

not really, its only 1 byte anyway. (only using 5 of the bits).

If you are only using 5 of the bits, then why not (for example) pack 3 data points into 2 bytes, thereby achieving a 1/3 reduction in the volume of data you have to send?