Go Down

Topic: Strange behavior with input and output port (Read 375 times) previous topic - next topic

leoneniko93

Apr 23, 2019, 09:10 pm Last Edit: Apr 23, 2019, 11:07 pm by leoneniko93 Reason: Insert the code typesetting
Good evening everybody.
I am new to the forum so please, if I am in the wrong section of the forum, let me know.
I am using Arduino ( Arduino Nano with Atmega328P ) and I am observing a strange behavior:
I need to switch on and off one of the digital pin of my board in a very fast way, so I implemented the following code:


Code: [Select]
int l=512;
int myArray[512] = {0};
void setup()
{
 pinMode(4, OUTPUT);
}

void loop() {
 for (int j = 0; j < l; j++) {
   if ((j % 2)==0) {myArray[j]=1;}
   else {myArray[j]=0;}
 }
 while(true) {for (int i = 0; i < l; i++) {
   bitWrite(PORTD, 4, myArray[i]);
 }}
}


By this my Arduino produces a square waves with a frequency of 0.5 MHz. But now things start to be strange: in the oscilloscope I observe an off time of 6-7 microseconds after some repetition...
Someone could give me an explanation about it and if it is possible to fix it?

PaulRB

Please read the forum guide in the sticky post, then modify your post above and put in the code tags. As you can see, the forum has corrupted your code because you did not use code tags.

PaulRB

Could the off time be caused by the code reaching the end of the array and re-starting at the beginning of the array?

leoneniko93

Could the off time be caused by the code reaching the end of the array and re-starting at the beginning of the array?
In my opinion, no, because it is just the while loop that is repeated... why he has to wait that time?... in order to verify it, if I remember correctly  (I don't have the oscilloscope here ), I have repeated the entire code considering a shorter sequence of bit, 8 indeed (10101010), and that effect is equal to the previous case...

I have also tried to use a 5V power supply instead of my pc to power the Arduino, in order to exclude any possible interference due to communication between the two device.

larryd

#4
Apr 23, 2019, 11:26 pm Last Edit: Apr 23, 2019, 11:29 pm by larryd
Quote
I need to switch on and off one of the digital pin of my board in a very fast way
Why?

How fast?

How many iterations are there here?
for (int j = 0; j < l; j++)
and
for (int i = 0; i < l; i++)



No technical PMs.
The last thing you did is where you should start looking.

leoneniko93

#5
Apr 23, 2019, 11:33 pm Last Edit: Apr 23, 2019, 11:34 pm by leoneniko93
Why?

How fast?

How many iterations are there here?
for (int j = 0; j < l; j++)
and
for (int i = 0; i < l; i++)




The achieved square waves ( 0.5 MHz ) is enough.
The number of iterations is fixed by l that in my case is 512, but is ok also for "l=whatever even number".
The first for is used to create the array that is scanned by the second for.

larryd

~2.7 MHz

Code: [Select]


void setup()
{
  pinMode(4, OUTPUT);

}

void loop()
{
  noInterrupts();
 
  while (true)
  {
    //~2.7MHz
    PIND = 0x10;  // Toggles pin D04
    //Toggle pins specific to UNO
    //PINB=0x20; //13  PINB=0x10; //12  PINB=0x08; //11  PINB=0x04; //10  PINB=0x02; //9  PINB=0x01; //8
    //PIND=0x80; //7   PIND=0x40; //6   PIND=0x20; //5   PIND=0x10; //4   PIND=0x08; //3  PIND=0x04; //2
  }

  interrupts();
 
}
No technical PMs.
The last thing you did is where you should start looking.

CrossRoads

The off time is likely the micros() and millis() processing, along with the loop() code processing.
You can use the noInterrupts() that LarryD posted to stop the interrupts.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

david_2018

#8
Apr 24, 2019, 01:12 am Last Edit: Apr 24, 2019, 01:12 am by david_2018
~2.7 MHz

Code: [Select]


void setup()
{
  pinMode(4, OUTPUT);

}

void loop()
{
  noInterrupts();
 
  while (true)
  {
    //~2.7MHz
    PIND = 0x10;  // Toggles pin D04
    //Toggle pins specific to UNO
    //PINB=0x20; //13  PINB=0x10; //12  PINB=0x08; //11  PINB=0x04; //10  PINB=0x02; //9  PINB=0x01; //8
    //PIND=0x80; //7   PIND=0x40; //6   PIND=0x20; //5   PIND=0x10; //4   PIND=0x08; //3  PIND=0x04; //2
  }

  interrupts();
 
}

Does it affect the frequency at all if you eliminate nearly all the code?
Code: [Select]

void setup(){
  pinMode(4, OUTPUT);
  noInterrupts();
}
void loop(){
    //~2.7MHz
    PIND = 0x10;  // Toggles pin D04
    //Toggle pins specific to UNO
    //PINB=0x20; //13  PINB=0x10; //12  PINB=0x08; //11  PINB=0x04; //10  PINB=0x02; //9  PINB=0x01; //8
    //PIND=0x80; //7   PIND=0x40; //6   PIND=0x20; //5   PIND=0x10; //4   PIND=0x08; //3  PIND=0x04; //2
}



larryd

I believe the last code you posted gives ~57kHz







No technical PMs.
The last thing you did is where you should start looking.

david_2018

I believe the last code you posted gives ~57kHz

Interresting, so going back to the beginning of the loop is much slower than a while loop, or do the interrupts get re-enabled at the end of setup?

leoneniko93

Thank to all the kind replies. I will surely try the  noInterrupts(); that seems the correct to idea to solve my problem. Thank also larryd for posting a faster solution respect to mine! I will surely give a try to it!
Since I am new to Arduino I am quite interested in the differences that the code posted by David_2018 has respect to the other one. Why it results slower?

larryd

#12
Apr 24, 2019, 02:25 am Last Edit: Apr 24, 2019, 03:13 am by larryd
I believe the last code you posted gives ~57kHz

I just measured the frequency, this should be 570kHz

It takes 1.3us for loop() to close and loop() to open again.
This is why the frequency is less.


Using while(true) results in less code, hence faster operation.
Frequency using while(true) measured at 2.703MHz




BTW
This gives 1MHz on pin 9 using TimerOne.h library

Code: [Select]

#include <TimerOne.h>

void setup()
{
pinMode(9,OUTPUT);

Timer1.initialize(1);  //1.0 MHz
Timer1.pwm(9,512);       // 50%

}

void loop()
{

}




No technical PMs.
The last thing you did is where you should start looking.

david_2018

It takes 1.3us for loop() to close and loop() to open again.

I didn't realize there was that much involved in loop(), I was thinking it was a single goto instruction to get back to the beginning.

larryd

#14
Apr 24, 2019, 04:24 am Last Edit: Apr 24, 2019, 04:26 am by larryd
There is serial checking also:

Code: [Select]

// See http://gammon.com.au/forum/?id=12625

#include <Arduino.h>

int main(void)
{
init();

#if defined(USBCON)
USBDevice.attach();
#endif

setup();
   
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
       
return 0;
}
   




No technical PMs.
The last thing you did is where you should start looking.

Go Up