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.
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?
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).
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.
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?
More technically, how much does its heat production increases with increased clock frequency.
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?