Go Down

### Topic: 1 Microsecond pulses (Read 6969 times)previous topic - next topic

#### Lithanial

##### Oct 04, 2012, 02:23 am
Hi,

I am new here and do not know much about programming, YET.

I am looking to control a gate two switch a HV supply to a transducer/receiver.

I need to control the gate with very short 5V pulses.  Approximately 1.2microseconds.  I hooked my arduino to a scope using the microsecond command, but the shortest pulse duration I can get is about 4 microseconds.

Does anyone know how to reduce this pulse duration down to 1.2 microseconds.

For my program:

Loop
30 microsecond (Low)
1.2 microsecond (High)
End Loop

If anyone can help me out with this short program I would very much appreciate it.

Thanks.

#### johnwasser

#1
##### Oct 04, 2012, 04:55 am
All the output pins are grouped in PORTs: PORTB, PORTC: PORTD.  Each port has a corresponding PIN register: PINB, PINC, PIND.  If you write a 1 to a bit in the PIN register the output pin will flip:

Code: [Select]
`PIND = 0x10;  // Toggle Pin 4 (Port D bit 4)PIND = 0x10;  // Toggle Pin 4  back (Port D bit 4)`

This should cause a very short pulse on Pin 4.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

#### RIDDICK

#2
##### Oct 04, 2012, 10:03 amLast Edit: Oct 04, 2012, 08:35 pm by RIDDICK Reason: 1

Code: [Select]
`PIND = 0x10;  // Toggle Pin 4 (Port D bit 4)PIND = 0x10;  // Toggle Pin 4  back (Port D bit 4)`

2 clocks faster should b this pulse:
PORTD = 1<<4;
PORTD = 0;

EDIT: oops - its not faster... but it makes sure that the pulse goes into the right direction...
-Arne

#### pylon

#3
##### Oct 04, 2012, 11:36 am
Maybe two direct port manipulations in full speed is too fast for the OP. If you need the 1.2us, you can use assembler commands to let the processor wait:

Code: [Select]
`__asm__("nop\n\t");`

Such a simple nop uses a bit more than 60ns.

#### Lithanial

#4
##### Oct 04, 2012, 12:06 pm

All the output pins are grouped in PORTs: PORTB, PORTC: PORTD.  Each port has a corresponding PIN register: PINB, PINC, PIND.  If you write a 1 to a bit in the PIN register the output pin will flip:

Code: [Select]
`PIND = 0x10;  // Toggle Pin 4 (Port D bit 4)PIND = 0x10;  // Toggle Pin 4  back (Port D bit 4)`

This should cause a very short pulse on Pin 4.

Thanks, I will try this today.

What exactly is this code saying?  I like to know what I am doing so I can learn from this.

#### RIDDICK

#5
##### Oct 04, 2012, 01:59 pmLast Edit: Oct 04, 2012, 02:01 pm by RIDDICK Reason: 1

What exactly is this code saying?  I like to know what I am doing so I can learn from this.

http://arduino.cc/en/Reference/PortManipulation
furthermore the datasheet of ur ATMEL mcu explains it in detail (search for "Toggling the Pin")...
-Arne

#### pylon

#6
##### Oct 04, 2012, 02:03 pm
This code

Code: [Select]
`PIND = 0x10;  // Toggle Pin 4 (Port D bit 4)PIND = 0x10;  // Toggle Pin 4  back (Port D bit 4)`

from johnwasser uses the feature of the PINx register to toggle the value of the selected bits (XOR, documented only in the datasheet 13.2.2).

The usual code for this is direct port manipulation:

Code: [Select]
`PORTD |= 0x10; // Switch on pin 4PORTD &= 0xEF; // Switch off pin4`

It's almost the same as the code from RIDDICK but without affecting all other pins of the same port (pins 0-7).

Both code snippets just tries to switch on and off a single pin as fast as possible, probably faster than you want. That's why you may have to insert the NOP assembler statements to wait some time before toggling the pin back.

#### johnwasser

#7
##### Oct 04, 2012, 03:10 pm

Code: [Select]
`PIND = 0x10;  // Toggle Pin 4 (Port D bit 4)PIND = 0x10;  // Toggle Pin 4  back (Port D bit 4)`

2 clocks faster should b this pulse:
PORTD = 1<<4;
PORTD = 0;

Problem is that will also set all the OTHER pins in PORTD to 0/LOW.  To avoid that you would normally use this code:
Code: [Select]
`PORTD |= 0x10; // Switch on pin 4PORTD &= 0xEF; // Switch off pin4`
but they require two read-modify-write cycles which I expect will make them slower than the PIN register.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

#### Lithanial

#8
##### Oct 04, 2012, 03:54 pm
I am getting a sawtooth pattern decay with this pulse?

#### pylon

#9
##### Oct 04, 2012, 05:16 pm
What did you expect? Rectangular pulses? That would mean you have absolutely no capacity on the line. How much of that is coming from your measurement equipment (a scope I guess)? Do you have the resolution to even see a rectangular signal if it was there?

#### MarkT

#10
##### Oct 04, 2012, 05:20 pm

I am getting a sawtooth pattern decay with this pulse?

You have set it as an OUTPUT?
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

#### MarkT

#11
##### Oct 04, 2012, 05:34 pm
This gives about 1.2us pulses, and disables interrupts during the pulse output to stop them occasionally stretching.

Disabling interrupts also means that any calls to digitalWrite () for pins in the D port in interrupt routines aren't broken by our direct port manipulation.

Code: [Select]
`void setup (){  pinMode (4, OUTPUT) ;  digitalWrite (4, LOW) ;  // or set to HIGH for low-going pulses.}void loop (){  pulse () ;  delayMicroseconds (5) ;}void pulse (){  cli () ;  PIND = 0x10 ;  __asm__("nop\n\t");  __asm__("nop\n\t");  __asm__("nop\n\t");  __asm__("nop\n\t");  delayMicroseconds (1) ;  PIND = 0x10 ;  sei () ;}`
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

#### pylon

#12
##### Oct 04, 2012, 06:54 pm
@MarkT: This gives you 4.2us pulses, try it out. delayMicroseconds() waits at least 4us even if the parameter is less than 4.

But you can change the code to:

Code: [Select]
`void pulse (){  cli () ;  PIND = 0x10 ;  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t");  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t");  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t");  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t");  PIND = 0x10 ;  sei () ;}`

This should result in a pulse of 1.2us.

#### Lithanial

#13
##### Oct 04, 2012, 07:25 pm
Thanks,

I finally got it.  There is a bit of overshooting at the top and bottom of the pulsing, but I can work with this.  Thanks.

#### MarkT

#14
##### Oct 05, 2012, 12:30 amLast Edit: Oct 05, 2012, 12:38 am by MarkT Reason: 1

@MarkT: This gives you 4.2us pulses, try it out. delayMicroseconds() waits at least 4us even if the parameter is less than 4.

But you can change the code to:

Code: [Select]
`void pulse (){  cli () ;  PIND = 0x10 ;  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t");  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t");  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t");  __asm__("nop\n\tnop\n\tnop\n\tnop\n\tnop\n\t");  PIND = 0x10 ;  sei () ;}`

This should result in a pulse of 1.2us.

Try it out - I tested it with 100MHz scope and get 1.19us pulses.  Am using the Arduino 1.0 software and avr-gcc 4.3.5
The code for delayMicroseconds has a comment saying that it is close to 1us when called with an argument of 1.

What version gives 4us then?

[edit:  Arduino 1.0.1 and arduino-0022 give me 1.19us as well]
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up

Please enter a valid email to subscribe