Generating binary sequences

On two outputs I need to continuously generate 5 bit binary sequences like for example: A = { 0,0,0,1,0} and B={1,0,0,1,1}.
How it should look like:
image

How to achieve this without using the delay function?

Welcome to the forum

Use millis() instead

See Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE

you can specify a sequence in two arrays along with an index for each array (if they need to run independent of one another)

a timestamp can also be captured and compared with millis to determine when to update the output, update the timestamp, increment and possibly wrap the indices into the arrays

Can you write me an example for one of the output signals, please?

This is a poorly written problem statement with insufficient detail. Here's some of the missing information that must be provided to even hope for an adequate answer: What's the bit rate? How accurate must it be? What "Arduino" board are you attempting to accomplish this with?

sounds like a school assignment

if I understand correctly what bitrate means, one bit should be sent every 30ms to both outputs.

I'm using Arduino UNO.

I want to test a logic gate where these two signals would be inputs.

So it sounds important that when the two signals are both transitioning, the pins on which they are output should change simultaneously.

So along with everythingg else you can glean from the heavies here or the internet (google), you will want to add

 Arduino direct port manipulation 

to your google/read list.

a7

For some definition of "simultaneously".

Good point.

So, I'll curl up with the data sheet later. :wink:

Looking to determine the delay one might measure between the transitions on pins of the same port being written at once.

I am sure it is not simultaneous. It may be very significantly not simultaneous for testing logic gates or devices made of them.

a7

Hi,
I think that if, for example, the ports of the "D" register are all set to output and set to LOW, when you set them to HIGH, as they are all in the same register, they go to HIGH simultaneously.

void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
}

void loop() {
  PORTD  = B10101010;  
  delay(500);
  PORTD  = B01010101;  
  delay(500);
}

They don't. They just go to HIGH within a few nanoseconds of one another. This creates a short interval of uncertainty, concerning the combined or aggregate value of the pins taken as a group. For example, if you have 8 pins on a port and they are together specifying a number, if it changes from 42 to 97 for example, there is a short period of time when numbers other than 42 and 97 can appear.

That is why clocked logic exists.

But a two pin logic gate only needs 4 states to cover all the possible combinations of inputs.
So to make things easy for yourself write the sequence in a grey code fashion, that is where only one bit changes at a time. That is simpler to write and I assume you will be inputting the result of the logic gate to your Arduino so you will have no problem coping with the input changes order when you create your truth table.

Is this code efficient to generate this sequence?

unsigned long previousMillis = 0;
unsigned long currentMillis = 0;

int count = 0;

void setup() {

  DDRD = B00001100;  // set D2 and D3 as output
}

void loop() {

  currentMillis = millis();


  if (currentMillis - previousMillis >= 0 && count == 0) {

    PORTD = B00001000;  // 1. D2 = 0 , D3 = 1
    count++;
  }


  else if (currentMillis - previousMillis >= 30 && count == 1) {

    PORTD = B00000000;  // 2.  D2 = 0 , D3 = 0
    count++;
  }

  else if (currentMillis - previousMillis >= 60 && count == 2) {

    PORTD = B00000000;  // 3. D2 = 0 , D3 = 0
    count++;
  }

  else if (currentMillis - previousMillis >= 90 && count == 3) {

    PORTD = B00001100;  //4.  D2 = 1 , D3 = 1
    count++;
  }

  else if (currentMillis - previousMillis >= 120 && count == 4) {

    PORTD = B00001000;  //5.  D2 = 0 , D3 = 1
    count++;
  } 
  
  else if (currentMillis - previousMillis >= 150 && count == 5) {

    count = 0;
    previousMillis = currentMillis;
  }
}

consider (corrected)

byte seq [] = {
    B00001000,
    B00000000,
    B00000000,
    B00001100,
    B00001000
};
unsigned idx;

#define Nseq sizeof(seq)

unsigned long msec;
unsigned long msecLst;

// -----------------------------------------------------------------------------
void loop()
{
    unsigned long msec = millis();

    if (msec - msecLst >= 30)  {
        PORTD   = seq [idx++];
        msecLst = msec;
        if (Nseq <= idx)
            idx = 0;
    }
}

volatile uint8_t *reg;
volatile uint8_t *out;

char s [80];

void setup()
{
    Serial.begin (9600);

    DDRD = B00001100;  // set D2 and D3 as output
}
1 Like

Those last two have more than one bit changing at any one transition. Not good for what you are trying to do, even with direct port addressing.

1 Like

not sure any delays between bit transitions occurring within the same register are significant considering the time timing between the register values of 30 msec

There is no output sampling going on while the inputs are being set. That means there are no race conditions and no need for port manipulation or any effort to make the pins toggle simultaneously. It is a canard.

I don't see any canard.

If one was to use a few of those sequenced outputs in an experiment, say looking into how a flip-flop made outta gates worked, and you wanted to drop S and R simultaneously, or raise them, maybe after having sequenced them properly, you might be wondering just how much difference in delay there could possibly be between port pins on the same port reaching the value they got set to.

And maybe finding you had to arrange an entirely different experiment protocol and Arduino assistant.

a7

I think it is unrealistic to expect to test nanosecond resolution timing with only an Arduino and no external hardware. Also, simultaneous transitions on almost any logic gates, produce a completely predictable response (namely, an undefined response) until the predictable stable logic states are achieved.

It's not that such timings could never be interesting, it's just that even a parallel port won't help you examine them, since you can not simultaneously set them and examine any output. The unavoidable delay in reading the output prohibits any examination of the transitional behaviour of the logic under test.

The special case of a circuit with memory, like the flip flop, could be measured that way, since it would hold data until the Arduino is ready to read. But I question the actual utility of that. Also I think that test would be needed extremely rarely (although the range of intended tests hasn't really been explained in this thread).