Pulse limiter?

Hello!

I'm building a project to limit pulse, but the pulse itself seems to be pretty weird. The pulse comes as a grounded signal, otherwise the wire is just not connected. How can I make Arduino to read this signal and then make it continue, but if the pulse's frequency is high enough, limit it?

The pulse is about 25 - 250hz, but the duty cycle is about 2%. So the pulse is LOW around 2% and 98% it's everything else than LOW, but I think Arduino cannot read it as HIGH, because it's under 1v or so...

Another problem is that the pulse changes pretty quickly, so the code should need to have ability to respond to the changes pretty quickly too. I think using delay() or delayMicroseconds() would just make the system fail, so delays aren't really usable. Interrupts could work, but I haven't got it working yet...

Thanks in advance! :)

Interrupts could work, but I haven't got it working yet...

Where's your code, maybe we could help?

but I think Arduino cannot read it as HIGH, because it's under 1v or so...

Where is that signal originating from? Is it open drain? Is it possible to use a simple pull-up? Otherwise you need a MOSFET/Transistor to push it over 3V for the Arduino to recognize.

The pulse is about 25 - 250hz, but the duty cycle is about 2%.

That's not really a problem for the Arduino, it's more than fast enough for that.

Seems to me that you need something like:

Pulse input connected to digital pin with internal pull-up resistor enabled.

Pin change interrupt used to duplicate the incoming pulse on a different digital pin. To get exactly the same electrical characteristics you would want to switch the output between OUTPUT LOW (tied to ground) and INPUT (high impedance).

Also use the pin change interrupt to trigger some frequency measuring code and apply a threshold to the measured frequency. I'm not sure what you mean by 'limit pulse'. If you mean shut off the output when the input frequency is over a threshold, that's easy enough. If you mean that the output frequency should be different to the input frequency then that implies that the output needs to be entirely generated by the Arduino and not just a copy of the input.

I don't think you've explain what voltage levels the external circuit is designed to support so you might need to add some hardware drivers between the Arduino and the raw inputs and outputs.

Thanks for quick replies!

By "limiting" the pulse I meant the frequency of it, so yes... Arduino should make the output itself. I think the high voltage doesn't matter in the other system, just the ground signal. If Arduino and the external system have a common ground, Arduino should be able to make right kind of a pulse.

Copying of the input should be possible with "change" interrupt, but how about "recording" the length of HIGH and LOW from the input, and the outputting the same pulse, with FALLING and RISING interrupts (for example)?

I think the high voltage doesn't matter in the other system, just the ground signal.

Does that mean if the Arduino pulls the signal to 5V the other device won't be harmed? Do you have a datasheet for that device to check that?

Copying of the input should be possible with "change" interrupt, but how about "recording" the length of HIGH and LOW from the input,

Why do you need to record the length of a HIGH (or LOW) if you just need the frequency? Install an interrupt handler for RISING edges on pin 2 or 3 and record the time between the two rising edges, the reciprocal value is the frequency. The output can be a PWM pin (for higher frequencies) or a simple digital output you control from the main loop.

Thanks for reply! :)

The actual problem is that the device is closed (no possible way to open and even check what it contains), and there is no datasheet. And another problem is that I'm not 100% sure about the ratio of LOW/HIGH, so it's not accurate with only the frequency. I could calculate the ratio and edit the code then though. And the device shouldn't be affected from the Arduino's +5v, everything else than GND is fine (except if it burns the wires or something...).

I'll try and post code soon! :)

Code:

int currentMicros, previousMicros, lowTime;
int currentTime, previousTime;

int input = 2;
int output = 3;

void setup() {
  pinMode(input, INPUT);
  pinMode(output, OUTPUT);
  digitalWrite(input, HIGH);
  digitalWrite(output, HIGH);
  attachInterrupt(0, calculateFrequency, RISING);
  Serial.begin(9600);
}

void loop() {
  currentTime = millis();
  if(currentTime - previousTime > 500) {
    previousTime = currentTime;
    Serial.println(lowTime);
  }
}

void calculateFrequency() {
  previousMicros = currentMicros;
  currentMicros = micros();
  lowTime = currentMicros - previousMicros;
}

I'm also using my Arduino Mega (2560, if it matters), to output some kind of pulse with this code:

void setup() {
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
}

void loop() {
  digitalWrite(2, HIGH);
  delayMicroseconds(450);
  digitalWrite(2, LOW);
  delayMicroseconds(50);
}

Uno is running the first code, and it writes about 512 - 520 to the serial, which is pretty close to right? How can I get the code more accurate, even 10 microseconds wrong can make the whole device fail... :D I was thinking something like this:

pulse = pulse - 15;

which would then make the output pretty close too 500 (+/- 5 probably).

All global variables changed in an interrupt handler have to be declared "volatile". Otherwise the compiler may do wrong optimizations. An int isn't big enough to hold the micros value, it has to be an unsigned long or clearer: uint32_t.

volatile uint32_t currentMicros, previousMicros, lowTime;

Thanks for help! :)

I've tested & edited my code little and I think it works now. I'll test it with the device later today and report back! :)