Pages: [1]   Go Down
Author Topic: Creating a pulse multiplier?  (Read 944 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
« Last Edit: May 22, 2012, 09:23:24 pm by polar8 » Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6613
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

1Hz input and 10Hz output is a pulse multiplier, not a divider. Google for "software phase locked loop".
Logged

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.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26969
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

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
__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|__|---|___
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: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 619
Posts: 33991
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
because you would need to wait for a couple input pulses before performing the arithmetic though, right?
wrong, look at reply #1.
Logged

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

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:
#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);
  
}
}
« Last Edit: May 22, 2012, 05:30:17 pm by polar8 » Logged

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

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:
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:
const int ledPin =  7;      // the number of the LED pin

int ledState = LOW;             // ledState used to set the LED
int 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);
  }
}
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26969
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

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:
for (int i = 0; i<10; i+i+1){
//write the LED hi, lo with delay that is = to outputInterval
digitalWrite (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:
// set output bit High, leave rest alone
PORTD = PIND | B10000000; // assumes ledPin is PortD, bit 7 for this example
delay(outputInterval);
// clear the output bit, leave rest alone
PORTD = PIND & B01111111;
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.

Pages: [1]   Go Up
Jump to: