Generate 60uS pulse

I would like generate 60uS pulse at the end of input pulse on. Enclosed is my code. There are 2 problem.

  1. the 60uS does not generate at pulse on.
  2. I did not generate 60uS pulse on every pulse input.

What I do wrong? Thanks in advance.

Best regards,

Victor

_70_uS_pulse.ino (1.9 KB)

What I do wrong?

You didn't post your code

I use Arduino Uno.

I need generator something like attached yellow waveform. Please kindly help.

What happens when you don't do any serial prints?

int outPin = 8;               // digital pin 8 as <70uS pulse for Chronos pulse mode
int inPin = 3;                // digital pin 3 as NRF clock input
int PulseInPin = 4;              // digital pin 4 as pulse width measurement


void setup() {
  pinMode(outPin, OUTPUT);    // sets the digital pin as output to generator a <70uS pulse
  pinMode(inPin, INPUT);      // sets the digital pin as input to detect when pulse on start
  Serial.begin(115200);       // setup for RS232
  pinMode(PulseInPin,INPUT);     // setup for pulse width measurement
}

void loop() {

  int val = digitalRead(inPin);
  static int state = 0;  
  // static int freq = 1000;
  static unsigned long PulseOnTime = 500;
  const int pulseon = 60;
  static int pulseoff = 929;
  static int currenttime = 1;

  PulseOnTime = pulseIn(PulseInPin, HIGH);
  currenttime = millis();
  pulseoff = PulseOnTime-pulseon;       // calculate pulse off time  
 // val = (digitalRead(inPin));           // Read NRF clock
      if (state == 0 && val == 1)  {  // When pulse on and state = 0, we would like generator a pulse
      digitalWrite(outPin, LOW);      // sets the pin off
      delayMicroseconds(pulseoff);         // pauses for (duty on - pulse time)
      digitalWrite(outPin, HIGH);     // sets the pin on
      delayMicroseconds(pulseon);          // pauses for 60 microseconds
      digitalWrite(outPin, LOW);      // sets the pin off
 
      state = 1;
      }
      else {
        if(val == 0) {
          state = 0;
          delayMicroseconds(1000);
        }
      } 
    Serial.print(currenttime); 
    Serial.print(">"); 
    Serial.print("PulseOnTime: "); 
    Serial.print(PulseOnTime); 
    Serial.print(" _state: "); 
    Serial.print(state);  
    Serial.print(" _ In: ");         
    Serial.print(val); 
    Serial.print(" _Out: ");         
    Serial.print(outPin); 
    Serial.print(" _???: "); 
    Serial.print(pulseoff);     
    Serial.print('\n');   
}

I tried comment out serial print. It seems improved. But still wrong. It was every 5 cycle to show 1 pulse. It is every other cycles.

I also tried different condition such as != 1, >0, !=0...etc. All those will not even generate pulse. It's very strange.

Based on that scope image: the incoming pulse lasts just over 200 µs, and comes in every 1 ms.
Those print statements take about 4 ms (roughly 11 characters per ms at 115200 bps). That's one major problem already, you will miss pulses completely.

Chingping:

  1. the 60uS does not generate at pulse on.

That is because you ask your code to wait a bit before generating the pulse:

      delayMicroseconds(pulseoff);         // pauses for (duty on - pulse time)

Now if you want the output pulse to start right when you get your input pulse, and you want it to last for pretty much exactly 60 µs, you have to drastically modify your code.

  1. use an interrupt to detect the incoming pulse for fastest reaction time. Set it to trigger on RISING for rising edge.
  2. use direct port calls to set the output pin, not the much slower digitalWrite() call.
  3. use a timer interrupt for switching off the pulse.

That way you will get 60 µs pulse (give or take a few clock pulses at 62.5 ns each - you can fine tune this a bit by tweaking the exact duration of the timer interrupt), which starts within some 300 ns from the incoming pulse.

Hi Wvmarle,

Thanks for your input. You are correct. The control loop time is too long due to pulseIn() function. I added a condition to use this function every second instead of every control loop. It work great now. Thanks a lot.

Best regards,
Victor

It seems Arduino Uno is not right board to support this project. The pulse is not reliable. I will try Arduino Zero as my next step.

Chingping:
It seems Arduino Uno is not right board to support this project. The pulse is not reliable. I will try Arduino Zero as my next step.

What is "not reliable"?

Unless you didn't give the full picture, I see this as a job the ATmega328p controller is perfectly capable of. The limitation is more likely with your programming skills, and switching to a Zero is not going to solve that.

Thanks for your reply. I do not have Arduino Zero with me. I will try to change the code to utilize interrupt.
When I say not reliable. I mean the pulse has been generate in right place in most case. Every once a while it has been generate in duty off cycle.

If all you want from the uController is a 60uS pulse a ESP32 can do it. I have found a few cases where the entire purpose of the ESP32 is to generate accurate pulses, even down to nano seconds https://www.instructables.com/id/625-Nanosecond-Resolution-Timer-for-Any-Microcontr/.

The ESP32 has a High Resolution Timer that is good to operate a few bits of code down to 50uS. I would venture that if no other code was ran but the code to cause a ESP32 reset or none at all, would get you your 60uS pulse.

ESP32 High Resolution Timer API High Resolution Timer (ESP Timer) - ESP32 - — ESP-IDF Programming Guide latest documentation


I am guessing that the UNO is off a bit due to its 'need' to handle the millisecond interrupt.

Idahowalker:
I am guessing that the UNO is off a bit due to its 'need' to handle the millisecond interrupt.

The images appear to show a pulse on a falling edge, rather than just on rising edge, as if there's an artifact in the input signal.

The ESP won't improve on this. Also if you think dealing with the millis() and micros() and similar functions in the background is an issue, just think of what the ESP is doing in the background... there's a reason they have the yield() function! For real time, precision timing work the AVR beats the ESP in many situations. Reacting quickly to interrupts is one fo them.

My spec is to generate a pulse less than 70 uS. So 50~70 is fine. I change the code to use interrupt. It's working great. Thanks a lot. It's my first Arduino project. I will use Arduino more going forward. That's very cool small board.

Well done!

I should note: we normally steer beginners clear from using interrupts, as there are lots of pitfalls. This is one of the rare cases where an interrupt is appropriate (for quick reaction to a rather fast changing signal).