Arduino Frequency at ouput pin

Hi guys;

I was curious to see what frequency, duty, period, time on and time off to an output pin. So I connect to a 10 k resistor ( +5 V - 10 k resistor - gnd ) and upload the Blink without delay. I have a picture of the oscilloscope display.

The strange part is why it is not 50 % duty ? The Frequency , that slow ? So an instruction of digitalWrite (pin, state ) is about 4 uS ?

Here is my results : T on = 3.8 uS T off = 4.6 uS Period = 8.4 uS
Frequency = 119047.619 F = 1 / Period
Duty Cycle = 45.2380952 Duty Cycle = ( T on / Period ) * 100

The test code : The picture : V side = 1 V / div Time side = 2 uS / div

/*
  size : 824 bytes
  
  Blink
  Without delay
  
  To see what frequency the output is.
  Connect the pin 12 with 1 10 K resistor  
 */
byte myled = 12; // pin 12 

void setup()
{                
  // init pin 12
  pinMode(myled, OUTPUT);     
}

void loop()
{  // display output 12 on/off without delay
  digitalWrite(myled, HIGH);   // set the LED on
  digitalWrite(myled, LOW);    // set the LED off
}

So guys, tell me of what you think.

Looks normal to me.

4us for a digitalWrite() makes sense. The digitalWrite() function has to map the pin number (13) to a port (PORTB) and a pin on that port (5) by doing array lookups. That takes time.

Also, it takes time to get from the bottom of the loop to the top, so there is some "down time" between writing LOW to the pin and writing HIGH, more than there is between writing HIGH and writing LOW. So it makes sense that the duty cycle is slightly less than 50%.

--
The MegaRAM shield: add 128 kilobytes of external RAM to your Arduino Mega/Mega2560

The strange part is why it is not 50 % duty ?

There will always be some loop() overhead time consumed to keep it from a perfect 50%

The Frequency , that slow ?

Yes, the digitalWrite function because it has to do a arduino 'abstracted' pin number to a actual AVR port & bit address conversion, does carry a speed penalty. Also because pin can be a variable rather then just a constant, that also adds to the converting.

So an instruction of digitalWrite (pin, state ) is about 4 uS ?

If maximum reading and writing to digital I/O pins is required then you can use direct port access methods. This will approach maximum speed possible per chip clock rate, but at the expense of not being portable between boards using 8/168/328 chips and ones using the 1280/2560 chip as they have different port & pin assignments.

http://www.arduino.cc/playground/Learning/PortManipulation

Lefty

Thank RuggedCircuits for your answer. I did this experiment to see what I will get. So top frequency is 119 k Hz - 4 uS on / off - minimum time. And that limitation has to take into consideration when designing certains applications / projects. Interresting.

Thank retrolefty for your answer.

If maximum reading and writing to digital I/O pins is required then you can use direct port access methods. This will approach maximum speed possible per chip clock rate, but at the expense of not being portable between boards using 8/168/328 chips and ones using the 1280/2560 chip as they have different port & pin assignments.

http://www.arduino.cc/playground/Learning/PortManipulation

I will into that....

Extensive discussion here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230286016

@westfw

Thank for the link. I will also look into it.

I saw you did that experiment, You measure 106.8 K Hz, mine is 119 K Hz, So your data is : Period = 9.363 uS Ton / T off = 4.681 uS. Interresting. It look like the Frequency average is 110 K Hz +/-10 K Hz Period = 9 uS +/- 1 uS. Not very precise. It look like to me that every board manufacture are the same spec, well more like +/- and are not precisely EXACT.

You measure 106.8 K Hz, mine is 119 K Hz, So your data is : Period = 9.363 uS Ton / T off = 4.681 uS.

I remember the output as being pretty close to a square wave. It was the faster direct port code where Ton and Toff drifted apart.

Interresting. It look like the Frequency average is 110 K Hz +/-10 K Hz Period = 9 uS +/- 1 uS. Not very precise.

When you use high-level functions like digitalWrite(), you're subject to changes in the library and/or compiler producing changes in timing. The thread I linked is almost three years old; that's several code versions ago. But notice the thread has additional info on:

  1. different pins have different speed
  2. getting higher speed using direct port access
  3. high-speed square waves using the pin toggle feature.
  4. WHY digitalWrite() is so slow (and variable.)

@westfw

That will explain a few things.

Ok, so how can I program the same program ( Blink without delay) using the ports. I am not sure how to program it. Can you guys give me an example code. I read the info, but I am comfuse which pin is which, and afraided to code and screw my ATMega chip.

Like :

// variable examples
// maybe setup examples 
void setup()
{
  //   an example in the setup
  DDRB = B00111111; // Hope I am correct in the setup
}
void loop()
{
  // example to display it
  PORTB = B00010000; // hope that I am correct to display
  PORTB = B00000000; // pin 12 on / off
}
void loop()
{
  // example to display it
  PORTB = B00010000; // hope that I am correct to display
  PORTB = B00000000; // pin 12 on / off
}

That will turn D12 on and off but will also turn D8 through D13 off.

You probably want to use the PIN register where writing a 1 will toggle the output:

void loop()
{
  // example to display it
  PINB = B00010000;   // Toggle pin D12 (Port B Bit 4) 
}

Even faster:

void loop()
{
  while (1 == 1)
      PINB = B00010000;   // Toggle pin D12 (Port B Bit 4) 
}

You might find the following worksheet useful for decoding what 'arduino' pin# is equal to what port/bit number.

https://spreadsheets.google.com/pub?key=rtHw_R6eVL140KS9_G8GPkA&gid=0

Lefty

@ retrolefty

Thank for the link. It will be usefull.

@johnwasser

Thank a lot. I begin to get it.

void loop()
{
  // example to display it
  PINB = B00010000;   // Toggle pin D12 (Port B Bit 4) 
}

What about inside the setup section ?

void setup() 
{
  // Any setup ?
}

void loop()
{
  // example to display it
  PINB = B00010000;   // Toggle pin D12 (Port B Bit 4) 
}
void setup() 
{
  // Any setup ?
  pinmode(12, OUTPUT);  // Yes, set it as an output pin
}

@johnwasser

Thank for the tip, again... :slight_smile:

Let recap... I get it. pinMode for setup and PINB= B00010000 for the pin I want. OK

Let code it the blink without delay

void setup()
{
  pinMode(12, OUTPUT);
}

void loop()
{
  PINB=B00010000;
  PINB=B00000000;

// or

 while (1==1)
   {
     PINB=B00010000;
     PINB=B00000000;
   }
}

Correct ? ---> I am trying to understand. And lean here.

     PINB=B00010000;
     PINB=B00000000;

Probably not. "PINB" would normally be the input port, and has a "magic" function of toggling the output when you write a 1 to some bit position (writing a 0 to PINB should do nothing.)
"PORTB" is the port where you write explicit ones and zeros and have them show up on the actual output pins (assuming that the pins are outputs.)

void setup()
{
  pinMode(12, OUTPUT);
}

void loop()
{
 while (1==1)
   {
     PINB=B00010000;  //  This line toggles D12 (turns it on if it's off, turns it off if it's on)
//     PINB=B00000000;  //  This line does nothing but waste time which is why I didn't put it in.
   }
}

@johnwasser

The raison I put the line PINB=B00010000; and PINB=B00010000; I was still thinking digitalWrite(pin, HIGH); digitalWrite(pin, LOW);
And I also think that pin 12 will stay HIGH, not turn on/off. Because when you do digitalWrite( pin, HIGH); the pin will stay "lock" at HIGH until a instruction say otherwise.

But to my discovery, just PINB=B00010000; IT CHANGING STATE .... but it will not "lock" to HIGH just like a digitalWrite...Humm ? What about PORTB =B00010000; Will it "lock" the pin to HIGH ?

Anyway, I did 3 set of program using PINB. The frequency is ... a BIG change... Like in my first experiment ( digitalWrite ) , to my discovery a HUGH change, It like driving at 60 km/h <-- exp 1 and you drive at 80 km/h <--exp 2 that a big jump to 160 km/h <--exp 3. And in exp 4, just a small change in speed.

The next 3 post will be my results including a picture of the waveform and the code.

There goes.......

Here the result of experiment no 2.

The setting : 0.5 uS / div 1 V /div

Ton = 0.8 uS Toff = 0.8 uS Duty = 50 % Period = 1.6 uS Frequency = 625 kHz

Code :

/*
 size : 630 bytes
 
 Blink without delay using ML instruction
 by using PINB <--- Pins Port B 
 
 To see what frequency the output is.
 Connect the pin 12 with a 10 K resistor. 
 
 With the help of johnwasser from the Arduino Forum.

*/

void setup()
{
  // setup pin 12
  pinMode(12, OUTPUT);
}

void loop()
{  
   // Methode A
  
  // turn on and off pin 12.
  PINB=B00010000;
  PINB=B00000000;

}

but it will not "lock" to HIGH just like a digitalWrite...Humm ?

Yes, the output pin will 'lock' high, that is, until you issue another PINB=B00010000 or a PORTB =B00000000 or a digitalWrite(pin#, LOW).

What about PORTB =B00010000; Will it "lock" the pin to HIGH ?

Yes, same as PINB will. Whatever the last command to change a pin's output state, it will stay that state until another command is executed that changes it's state, or a hardware reset.

Lefty

Here the result of experiment no 3.

The setting : 0.2 uS / div 1 V /div

Ton = 0.24 uS Toff = 0.26 uS Duty = 48 % Period = 0.5 uS Frequency = 2 M Hz

Code :

/*
 size : 630 bytes
 
 Blink without delay using ML instruction
 by using PINB <--- Pins Port B 
 
 To see what frequency the output is.
 Connect the pin 12 with a 10 K resistor. 
 
 With the help of johnwasser from the Arduino Forum.

*/

void setup()
{
  // setup pin 12
  pinMode(12, OUTPUT);
}

void loop()
{
  // another methode 
// Turn pin 12 on and off
 while (1==1)
   {
     PINB=B00010000;
     PINB=B00000000;
   }

}