Go Down

### Topic: Creating a pulse multiplier? (Read 2706 times)previous topic - next topic

#### polar8

##### May 22, 2012, 08:49 pmLast Edit: May 23, 2012, 04:23 am by polar8 Reason: 1
I'd like to use the Arduino to create a pulse divider. My input is a 1PPS, 8us 5v pulse from a GPS that I will use for timekeeping. I'd like to use that to create a 10hz 10us 5v output pulse.

Any suggestions or example projects to look at?

Thanks!

#### dc42

#1
##### May 22, 2012, 09:28 pm
1Hz input and 10Hz output is a pulse multiplier, not a divider. Google for "software phase locked loop".
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

#### CrossRoads

#2
##### May 22, 2012, 09:38 pm
There's 1,000,000uS in a second.
(1,000mS in a second)
So once a second you're like a little burst of 10uS pulses at a 10 Hz rate?

from: High for 8uS, Low for 999,992us
__|--|_____________________________________________________________|--|_____________
to: High for 10uS, Low for 99,990uS, repeat 10 times, repeat with next 1PPS pulse
__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|___
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.

#### polar8

#3
##### May 22, 2012, 10:07 pm
Ok, I understand how it would be a multiplier.

There's 1,000,000uS in a second.
(1,000mS in a second)
So once a second you're like a little burst of 10uS pulses at a 10 Hz rate?

from: High for 8uS, Low for 999,992us
__|--|_____________________________________________________________|--|_____________
to: High for 10uS, Low for 99,990uS, repeat 10 times, repeat with next 1PPS pulse
__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|___

Yes! That's what I would like to implement. I'm not sure how to do it though, because you would need to wait for a couple input pulses before performing the arithmetic though, right?

#### Grumpy_Mike

#4
##### May 22, 2012, 11:27 pm
Quote
because you would need to wait for a couple input pulses before performing the arithmetic though, right?

wrong, look at reply #1.

#### polar8

#5
##### May 23, 2012, 12:28 amLast Edit: May 23, 2012, 12:30 am by polar8 Reason: 1
Ok, since this is my first Arduino program I have started simple in hopes of moving my way up.

What I have succeeded in doing is measuring an interval between button presses, then blinking an LED at a fraction of that interval for a certain number of times.

The problem is that while the LED blinks correctly (at a rate proportional to the interval measured), I can only get it to do it for a fixed number of times using my While loop.

I would like to modify this so that the LED blinks at a fraction of the latest interval measured, until the next button press is registered (signalling a new interval.)

Code: [Select]
`#define  DELAY_START   HIGH    #define  DELAY_END   !DELAY_START   int ledPin = 3;    int inputPin = 2;   int x;long start, duration, fduration, interval;void setup() {  pinMode(ledPin, OUTPUT);  pinMode(inputPin, INPUT);      Serial.begin(9600);}void loop(){  while( digitalRead(inputPin) != DELAY_START   ) ;  start = millis();  while( digitalRead(inputPin) != DELAY_END   ) ;  duration = start - millis();  fduration = 0 - duration;                //for some reason my duration was negative so this makes it positive  interval = fduration / 10;  Serial.println(fduration);  for(int x = 0; x < 10; x++){  digitalWrite(ledPin, HIGH);  delay(10);  digitalWrite(ledPin, LOW);  delay(interval);  }}`

#### polar8

#6
##### May 23, 2012, 04:26 am
Well I abandoned the attempt above because I realized that using delay() wasn't going to work as it pauses the entire program. Instead I found an example, called Blink Without Delay, and added/modified the following lines:

Code: [Select]
` outputInterval = interval / 500;  if(currentMillis - previousMillis > outputInterval)`

Since I am trying to create subintervals out of an input pulse, that was in hopes of taking the measured interval and dividing it by a constant to get a faster pulse.

However that part didn't work, the output pulse stayed precisely 2x slower than the input pulse regardless of what I changed the constant to be.

Any suggestions?

My full code:
Code: [Select]
`const int ledPin =  7;      // the number of the LED pinint ledState = LOW;             // ledState used to set the LEDint pin = 2;long previousMillis = 0;        // will store last time LED was updated// the follow variables is a long because the time, measured in miliseconds,// will quickly become a bigger number than can be stored in an int.long interval;           // interval at which to blink (milliseconds)long outputInterval;void setup() {pinMode(ledPin, OUTPUT);    pinMode(pin, INPUT);Serial.begin(115200);}void loop(){    interval = pulseIn(pin, HIGH);  Serial.println(interval);  unsigned long currentMillis = millis(); outputInterval = interval / 500;  if(currentMillis - previousMillis > outputInterval) {    previousMillis = currentMillis;      if (ledState == LOW)      ledState = HIGH;    else      ledState = LOW;    digitalWrite(ledPin, ledState);  }}`

#### CrossRoads

#7
##### May 23, 2012, 06:19 am
millis() returns unsigned long change your time variables to be unsigned long also.

You are only changing ledState one time after the end of the pulse measuring.
You need a for next loop after measuring the pulse width:
Code: [Select]
`for (int i = 0; i<10; i+i+1){//write the LED hi, lo with delay that is = to outputIntervaldigitalWrite (ledPin, HIGH);delay (outputInterval);digitalWrite (ledPin, LOW);delay (outputInterval);}`
That will get you to a set of pulses at the end of a pulse measurement; I think that will look like a burst of pulses during the off time of your initial pulse.

digitalWrite might slow the response down, in which case you use direct port manipulation:
Code: [Select]
`// set output bit High, leave rest alonePORTD = PIND | B10000000; // assumes ledPin is PortD, bit 7 for this exampledelay(outputInterval);// clear the output bit, leave rest alonePORTD = PIND & B01111111; `
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.

Go Up