Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Pages: [1] 2   Go Down
Author Topic: Digital Outputs  (Read 1926 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi there, my project requires me to generate a 1.2 MHz signal.  Is there a way to make a digital pin write out at that speed?
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 555
Posts: 27683
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes. Search  for "Direct Port Manipulation".
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using the code in the arduino page, as well as some code that someone else posted online, and I'm not getting any signal being outputted. 

Just to test, my code is:
int ledPin = 4;                 // LED connected to digital pin 13

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  PORTD = B00010000;
  PORTD = B00000000;
}

I'm using a Mega2560, could that be why it's not working?  Or am I doing something completely wrong?
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 131
Posts: 8690
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

How do you know it's not working, you can't see that frequency.

Also it may not be possible to get exactly 1.2Mhz and using a loop the waveform won't be a 50% duty cycle. Does any of that matter to your application?

EDIT: On the 2560 pin 4 is PORTG bit 5. You are using PORTD bit 4 which is not connected to anything on the Mega.

Try PORTB bit 7 for the LED, but as I said at that speed you need instruments to see it.

Try

Code:
void setup()
{
  pinMode(13, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  PORTB = B10000000;
  PORTB = B00000000;
  delay (1000);
}

To verify that the LED is blinking.

______
Rob
« Last Edit: March 08, 2012, 07:00:36 pm by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Awesome, thank you for all the help.  Duty cycle is not an issue, but I do need to be close to 1.2 MHz.  I will fiddle with it.  Is there any way I can induce a delay that's less than a microsecond to control the frequency?

I was using an oscilloscope to see the signal.
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 131
Posts: 8690
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is there any way I can induce a delay that's less than a microsecond to control the frequency?
At that frequency the only real option is to insert dummy instructions, for example

asm ("nop");

will insert a 62.5nS delay. So write the tightest loop you can (as above) then if it's too fast start adding NOPs. If it's too slow get an ARM smiley

Bottom line is that your basic resolution is 62.5nS so you should be able to tune it to within that res.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 555
Posts: 27683
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you need
DDRB = B1111111; // for all 8 bits to be outputs on Port B

following this info:
Code:
/* Each port is controlled by three registers, which are also defined variables in the arduino language.
The DDR register, determines whether the pin is an INPUT or OUTPUT. (DDRx)
The PORT register controls whether the pin is HIGH or LOW.          (PORTx)
The PIN register reads the state of INPUT pins set to input with pinMode(). (PINx)

DDR and PORT registers may be both written to, and read.
PIN registers correspond to the state of inputs and may only be read.

Example
DDRD = B11111110;  // sets Arduino pins 1 to 7 as outputs, pin 0 as input
DDRD = DDRD | B11111100;  // this is safer as it sets pins 2 to 7 as outputs
                  // without changing the value of pins 0 & 1, which are RX & TX

PORTD = B10101000; // sets digital pins 7,5,3 HIGH
*/[code]
[/code]
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How do you know it's not working, you can't see that frequency.

Also it may not be possible to get exactly 1.2Mhz and using a loop the waveform won't be a 50% duty cycle. Does any of that matter to your application?

EDIT: On the 2560 pin 4 is PORTG bit 5. You are using PORTD bit 4 which is not connected to anything on the Mega.

Try PORTB bit 7 for the LED, but as I said at that speed you need instruments to see it.

Try

Code:
void setup()
{
  pinMode(13, OUTPUT);      // sets the digital pin as output
}

void loop()
{
  PORTB = B10000000;
  PORTB = B00000000;
  delay (1000);
}

To verify that the LED is blinking.

______
Rob

Awesome, that totally works!  Using your sample code, and getting rid of that delay(1000), I was able to get a 934kHz signal, which is usable.

My only question now is that this is done by NOT using ANY other commands.  I'm using my microcontroller to read in a signal and perform some calculations on it and output it to a serial, as well as creating this signal.  Once I introduce those other commands, it's going to slow this signal down right?  Is there any way around that, or is my knowledge of arduino code just too basic?
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 131
Posts: 8690
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
it's going to slow this signal down right?
Yep.

Quote
Is there any way around that
Not if you need the signal to be constant.

If you are happy to read and calculate outside this loop then you can do that, but if this extra work has to be done constantly you are in trouble.

In this case you are better using one of the hardware timers, they can be "set and forget" with no further software intervention and they are not affected by any code running.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Montreal
Offline Offline
Faraday Member
**
Karma: 31
Posts: 2625
Per aspera ad astra.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is there any way around that, or is my knowledge of arduino code just too basic?
The way around is to program one of the timers to drive PWM pin.
http://arduino.cc/playground/Code/PwmFrequency
Logged

Western New York, USA
Offline Offline
Faraday Member
**
Karma: 42
Posts: 4464
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This can be done by using the 'Toggle OC2A on Compare Match' mode along with the 'Clear Timer on Compare Match (CTC)' mode of Timer/Counter2.  This sounds complicacted, but as I recall it only takes about four instructions, all in setup().

The disadvantage of this technique is that the output pin is fixed by the hardware.  It also ties up a timer (timer 2 in this case).

The advantage is that this technique does not use any interrupts and does not use any processor time once it is set up.

I have some (untested) code around here somewhere, I'll try to dig it up tomorrow and test it out.


Don
« Last Edit: March 12, 2012, 10:06:14 pm by floresta » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you, I appreciate it.

I'll also try modifying the PWM timer.
Logged

Western New York, USA
Offline Offline
Faraday Member
**
Karma: 42
Posts: 4464
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I have some (untested) code around here somewhere, I'll try to dig it up tomorrow and test it out.

Here it is - it worked for me!

Code:
//  Arduino - v1.0
//  Arduino Duemilanove

#define outpin 11                                  // OC2A pin - cannot be changed
#define clockFrequency 16000000                    // Arduino clock frequency
#define outputFrequency 1000000                    // desired output frequency
#define prescaleFactor 1                           // the only choice to get 1 MHz out

void setup ()
{
  TCCR2B = B00000001;                               // set CS20, clear CS21, CS22 and WGM22
  TCCR2A = B01000010;                               // set COM2A0 and WGM21, clear COM2A1 and WGM20

  OCR2A  = ((float)clockFrequency / (outputFrequency * 2 * prescaleFactor)) -1;  // timer data

  pinMode(outpin, OUTPUT);                          // turn on output pin   

// the timer runs with no additional code and no use of interrupts
// do whatever else you want to do here

}

void loop ()
{
// do whatever else you want to do here
}



Don
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 23
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's perfect, exactly what I need, thank you!

Just to confirm, is that pin the same pin on the Mega2560?  Or is there a place I can check which pin is what online?
Logged

Western New York, USA
Offline Offline
Faraday Member
**
Karma: 42
Posts: 4464
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Just to confirm, is that pin the same pin on the Mega2560?  Or is there a place I can check which pin is what online?

I wouldn't count on it.  As far as I can tell from the hodgepodge that they call a 'Schematic' diagram it is Pin 10.

By the way you should be able to turn the square wave off with TCCR2B = B00000000;  and back on again with another TCCR2B = B00000001;.


Don

Edit:  It looks like it is indeed digital pin 10 according to:  http://arduino.cc/en/Hacking/PinMapping2560
« Last Edit: March 13, 2012, 04:26:32 pm by floresta » Logged

Pages: [1] 2   Go Up
Arduino Forum upgrade scheduled for Monday, October 20th, 11am-4pm (CEST). Sorry for the inconvenience!
Jump to: