PORTD output problem [SOLVED]

Hello!
I’ve made a little sketch to show my problem. This is programm which create array of binary digits and then pull out it into PORTD.

const byte size = 16;
const byte outsize = 36;
const byte OnePin = 5;
const byte ZeroPin = 6;
byte source[size] = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0};
byte channel[outsize];
unsigned long time;


void setup() {
        //Serial.begin(9600);
	DDRD |= 1<<OnePin;
        DDRD |= 1<<ZeroPin;
 	for (byte j = 0; j < outsize; j++){//fill array with 1
		bitSet(channel[j], OnePin);
                bitSet(channel[j], ZeroPin);
	}       
}

void CreateArrays(){//make array for source[16] with parity bit and stop bit.
	byte ones = 0;
	for (byte i = 0; i < size; i++){
          if(source[i] == 1){
			bitClear(channel[2*i+1],OnePin);
			bitSet(channel[2*i+1],ZeroPin);
			ones++;
		}else{
			bitClear(channel[2*i+1],ZeroPin);
			bitSet(channel[2*i+1],OnePin);
		}
        }
	if ( bitRead(ones,0) == 0 ){//parity bit
			bitClear(channel[2*size+1],OnePin);  
	}else{
			bitClear(channel[2*size+1],ZeroPin);
	}
	bitClear(channel[outsize-1],OnePin);//stop bit
	bitClear(channel[outsize-1],ZeroPin);
}


void MoveArrOut(){
//time=micros();
noInterrupts();
	for (int i = 0; i < outsize; i++){
		PORTD = channel[i];
	}
		PORTD = channel[0];
interrupts();
//Serial.print(micros() - time); Serial.println(" micros");
}


void loop(){
	CreateArrays();
	MoveArrOut();
}

i’m waiting to see what time one packet of bytes go out, but i get different time(from 20 to 24 us/packet). I run this on my arduino 2009. Tried to change pins, enable interrupts… nothing helped. What can be a reason for such situation?

PS. i watched outputs on oscilloscope and it confirmed that some bits are longer in “1” or “0” than it should be.

Thanks.

UPD. Pictures:
http://i49.tinypic.com/1j0sp0.jpg - normal pic
http://i50.tinypic.com/wl4xvs.jpg - “wide” pic - synchro fail, cause output error
http://i47.tinypic.com/107koxv.jpg - close look to normal pic
http://i47.tinypic.com/b4hs9g.jpg - close look to “wide” pic

Probably, micros() couldn’t be very accurate to measure time < 100 usec. I’d stick to oscilloscope.
To make it even faster, use pointer to address array, and unrolled loop, 36 lines of code is not much.

i watched outputs on oscilloscope and it confirmed that some bits are longer in "1" or "0" than it should be.

What does "longer than it should be" mean? How long should they be? Can you show us the oscilloscope output?

Magician:
Probably, micros() couldn’t be very accurate to measure time < 100 usec. I’d stick to oscilloscope.
To make it even faster, use pointer to address array, and unrolled loop, 36 lines of code is not much.

Thanks for answer.
unrolled loop? You mean change loop for 36 static lines? Unfortunately, i cant do this, cause in my project will be one more function with data reading from inputs.

And what about unstable output? Any ideas?
This looks like:
HLHHHLHHHLHHHL
HHHLHHHLHHHLHH

and sometimes like:
HLHHHLHHHLLLHHHL
HHHLHHHLHHHHHLHH

what shouldnt be… and such lenght changing may be randomly on each output bit.

Are you sure you're capturing fast enough? With your code you should never have both lines HIGH at the same time. If you're capturing with about the same speed as the Arduino is putting out the values, such "rounding" errors can happen. Can you show the scope output (screen dump)?

pylon: Are you sure you're capturing fast enough? With your code you should never have both lines HIGH at the same time. If you're capturing with about the same speed as the Arduino is putting out the values, such "rounding" errors can happen. Can you show the scope output (screen dump)?

hmm... you made a mistake) in my array each 2i element is 1, cause first it filled by 1 and then i change 1 to 0 in first or second line(for each 2i+1 element):

if(source[i] == 1){
            bitClear(channel[2*i+1],OnePin);
            bitSet(channel[2*i+1],ZeroPin);
            ones++;
        }else{
            bitClear(channel[2*i+1],ZeroPin);
            bitSet(channel[2*i+1],OnePin);
        }

and i use fast enough oscilloscope of course. http://i49.tinypic.com/1j0sp0.jpg - normal pic http://i50.tinypic.com/wl4xvs.jpg - "wide" pic - synchro fail, cause output error http://i47.tinypic.com/107koxv.jpg - close look to normal pic http://i47.tinypic.com/b4hs9g.jpg - close look to "wide" pic

Lerk:

Magician:
Probably, micros() couldn’t be very accurate to measure time < 100 usec. I’d stick to oscilloscope.
To make it even faster, use pointer to address array, and unrolled loop, 36 lines of code is not much.

Thanks for answer.
unrolled loop? You mean change loop for 36 static lines? Unfortunately, i cant do this, cause in my project will be one more function with data reading from inputs.

Unrolling the loop and writing the 36 lines will affect code size, and may have an effect on execution speed and it would be doing the same function as your looping code. It lets you eliminate the comparisons and the need to examine data and such. It gives you the most control over execution speed.

You don't have a problem of speed or length of a signal, they single bits are of equal size but there is a problem with the codes. You get more situations where the OnePin and the ZeroPin are low at the same time than you like. Is this correct?

Is it your intention to set the parity bit only on one pin and not on the other? What do you wanna achieve?

Ah, I see now, you're getting to many spikes. You are expecting about ten on every pin but you get 14 or 15. It seems to send all the bits and after the stop bit it starts over somewhere in the middle of the bit word. Is that your problem? If you have this problem do you always get the same picture or does the "faulty" picture change?

The main idea(not mine idea) of this code is for “1”:
On line A: HL
On line B: HH
for “0”:
On line A: HH
On line B:HL
Parity bit is to get (2i+1) count of HL on line A, and (2i) count of HL on line B. And then stop bit, which is just HL for both lines.

For the 4bit source word(1010) i should get:
A: HLHHHLHH<-data HL<- parity HL< - stop
B: HHHLHHHL<-data HH< -parity HL< - stop
and i often get this with normal syncronisation(for rising edge with 30us till fall - it’s pause between packets).

But sometimes i get wrong picture(forgot made photo with proper synchro to show), it looks like:
A: HLHHHLLLLHH<-data HL<- parity HL< - stop
B: HHHLHHHHHHL<-data HH< -parity HL< - stop
or:
A: HLHHHLHH<-data HHHHL<- parity HL< - stop
B: HHHLHHHL<-data HHHHH< -parity HL< - stop
or:
A: HLHHHLHH<-data HL<- parity HLLLL< - stop
B: HHHLHHHL<-data HH< -parity HLLLL< - stop
and so on. “long” bit appears randomly in packet and this is problem. (it’s not about code problem - it’s work even with wrong timings, but i have a great interest to reslove this problem).

Sorry, I deleted my post, digging a little bit into USART, I can’t find evidence that it could affect pin 5 & 6. The same time, I’m curious, what happened when Rx pin triggered by direct port manipulation? Logically, it should triggered USART interrupt as well, ( it’s configured, right?).
It shouldn’t be a problem, with noInterrupt, but the easiest way to clear is to try another port B or C.
Other things, pins 5 & 6 is TIMER0 PWM, and it could works with noInerrupt active, as PWM- hardware driven.

Magician: Sorry, I deleted my post, digging a little bit into USART, I can't find evidence that it could affect pin 5 & 6. The same time, I'm curious, what happened when Rx pin triggered by direct port manipulation? Logically, it should triggered USART interrupt as well, ( it's configured, right?). It shouldn't be a problem, with noInterrupt, but the easiest way to clear is to try another port B or C. Other things, pins 5 & 6 is TIMER0 PWM, and it could works with noInerrupt active, as PWM- hardware driven.

is there any way to setup only two bits of port with variable?

PS. tried other ports - the same result. cycle unrolling helped get 1.3Mhz freq, but also doesnt resove problem.

I ran your sketch on my UNO and attached my scope. I have a straight signal always (screenshot attached), I never got the artifacts you showed in your photos. Do you trust your scope 100%? Do you have another Arduino to try?

Hello. I've rewrited programm in AVRStudio and made a little work with disassembler. At now i can say definitely, that at high frequency and with a lot of variables in programm compiler may create different code for strings like "PORTD = array[31]" and "PORTD = array[32]". In my case i have a situation, when such strings for array[0-31] have 2 asm commands and array[32-35] - 5 asm commands. So this lead us to different signal length on oscilloscope. Then i've optimized my code, and now problem solved.

As for other question in topic: 1. what's happening when you try to change PORTD value, if some bits are input? This is simple - it's turn on/off pullup resistor.(14.2.1 in datasheet). 2. RX/TX pin is configurable pins, so if you make your code in AVRStudio you can(if you wish) configure it as UART. Other way it's just another 2 pins.

Thx 2 all.