Help flashing LEDS for specific amount of time using sensor

Hi - I have a sensor sending a high/low signal to pin 12 of an Arduino Mega. Once I receive the signal I would like to flash the LEDs for a defined period of time.

For example, signal is received, LEDS turn on for 75 microseconds and then turn off.

My programming skills are very rudimentary. I have a very basic sketch that works but I can't adjust the time yet.

How could I modify this to be able to set the time it is on and then turns off?

const int RED = 9;
const int GREEN = 10;
const int BLUE = 5;

const int sensor = 12;

void setup()
{


pinMode(sensor, INPUT);
    pinMode(RED, OUTPUT);
        pinMode(GREEN, OUTPUT);
            pinMode(BLUE, OUTPUT);
}

void loop(){

   if(digitalRead(sensor) == HIGH){
          analogWrite(RED, 254);
        analogWrite(GREEN, 254);
       analogWrite(BLUE, 254);
      }
    

  if(digitalRead(sensor) == LOW) {
       
      analogWrite(RED, 40);
        analogWrite(GREEN, 40);
       analogWrite(BLUE, 40);
    }
 
}

You're unlikely to see a LED that lights for only 75 microseconds, even if you used digitalWrite instead of analogWrite.

What are you trying to do?

1 Like

Where’s the sensor input ?
Where’s the microsecond timing ?
Thanks for using code tags…, you can also try the auto-format tool - to realign your indenting…
Cheers

I’m trying to pulse the light for a specific time. Turn it on for x amount of time then close it. And it’s triggered by pin 12.

Take a look at the blink without delay example, and the state change detection example in the IDE.
Change the timescales.
Maybe think about not using analogWrite

Pin 12

This is why im reaching out here. The code above works good so far on my machine but the pulse is a little bit too long so I need to implemented timing to the code and I don’t know how.

The current pulse is around 20ms I need to reduce it below that. 10-15 would be great. If it could even be shorter would be better.

What pulse?

Reason I use analog write is because I need to send PWM to my DAC who then sends .5-2.5v to my ledDriver (picobuck) for dimming.

The pulse width of the LED when it’s on. Measured on my scope.

Think how many cycles of 980 or 490 Hz PWM you're going to see in 75 microseconds.

75us not needed. 10-15ms or lower would be great

Since all your three LED outputs have the same duty cycle (254 or 40) can you live with a single timer output driving all three inputs to you DAC?

This does that, using timer3 to produce a 10kHz PWM on pin 5. It idles at ~15.7% duty and increases to ~99% for 1mS.

At these settings you get ~10 cycles of the high-duty PWM.

#define PWM_PERIOD  1599    //#     PWM freq = 1/((K+1)*62.5E-09)
#define HIGH_DUTY   1588    //#     DC = K/PWM_PERIOD
#define LOW_DUTY    250     //#     DC = K/PWM_PERIOD
#define PULSE_LEN   1000ul  //uS    length of high-duty PWM pulse

const uint8_t pinPWM = 5;       //OC3A
const uint8_t pinSensor = 12;   //sensor input
const uint8_t pinDbg = 3;

uint8_t
    nowSensor,
    lastSensor;
uint32_t
    tNow,
    tBlip;

void setup()
{
    //set up timer3
    //  WGM14 TOP is ICR3 -> 1599 gives 10kHz
    //  prescaler == /1    
    //  OC3A sets on BOTTOM, clears on COMPARE
    TCCR3A = _BV(COM3A1) | _BV(WGM31);
    TCCR3B = _BV(WGM33) | _BV(WGM32) | _BV(CS30);
    ICR3 = PWM_PERIOD;
    OCR3A = LOW_DUTY;

    pinMode( pinDbg, OUTPUT );
    pinMode( pinSensor, INPUT);
    lastSensor = digitalRead( pinSensor );
    pinMode( pinPWM, OUTPUT);
        
}//setup

void loop()
{
    static bool
        bFlag = false;

    switch( bFlag )
    {
        case    false:
            //look for sensor input to transition low to high
            nowSensor = digitalRead( pinSensor );
            if( nowSensor != lastSensor )
            {
                lastSensor = nowSensor;
                if( nowSensor == HIGH )
                {
                    //transitions seen
                    //set OC to high-duty                    
                    OCR3A = HIGH_DUTY;
                    //save the micros count when we went high
                    tBlip = micros();
                    //and move to time the period
                    bFlag = true;                
                    //for debugging/scoping  
                    digitalWrite( pinDbg, HIGH );
                    
                }//if
            
            }//if
            
        break;

        case    true:            
            //when blip done...
            if( (micros() - tBlip) >= PULSE_LEN )
            {                
                //go back to low duty cycle
                OCR3A = LOW_DUTY;
                //go back to look for next low-transition on sensor input
                bFlag = false;
                //for scoping
                digitalWrite( pinDbg, LOW );
                
            }//if
            
        break;
        
    }//switch    
 
}//loop
1 Like

I think rather that persisting with this persistent back-and-forth-back-and-forth, you need to sit down and describe in excruciating detail, your project.

  1. What is its purpose?
  2. What are the precise specifications?
  3. What parts are you assembling? A complete list.
  4. A connection diagram.
1 Like

Hi, @marvguitar

What is your application?
What are you trying to do?
What is you input source?
What do you feed the Mega output too, and what is it supposed to do.

Can you please tell us your electronics, programming, arduino, hardware experience?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Film scanner (digitizing Motion picture film)

This is explained in first post. I’m trying to turn on RGB leds for x amount of time and then turn it off. The code I currently use is working but if I could shorten the pulse/time the leds are on, it would work better.

Would be great to have precision in milliseconds. In op, I mentioned an example in microseconds but that is not needed.

The trigger is a fiber optic laser, (Keyence fs-n41p with fu-20 sensor)

The hardware is working - the arduino is getting the Keyence sensor signal on pin 12 on arduino mega. 3.3v are sent to this pin when the sensor is triggered.

The RGB leds flash for approx 20ms according to my scope. As you can see in my code above there is no timing code, I need help with that so I can turn on LEDs for x amount of time and turn them off after.

Arduino mega output pin 9,10,5 are each color on the LED chip (RGB) and feed analog PWM signal 0-254 to a DAC who then converts that to 0.5-2.5V so the LED driver can use this voltage for dimming the LEDs. This is needed so the machine vision camera doesn’t flicker. PWM dimming is demonic for my application. The output signal going to pin 9,10 and 5 is the one that needs to be timed.

Very little of everything- my machine is working but having control over the pulse width would make it much better.

Right now the sensor is sending a 3.3v signal to pin 12, pin gets high, start timing and fire up the LEDS for the duration needed(could be varied in code, millisecond precision if that’s all that can be done) then once the set duration is done, turn the LEDs off.

Hopefully that helps clarify.

Your solution is incredible. I never seen such precision so far it's crazy. Only 1 LED works right now will try to add the other ones and try to understand the code better but my goodness thank you!

Here's a version that uses three timers to give 3 PWM outputs and an external interrupt to sense the rising edge on the sensor input:

#define PWM_PERIOD  1599    //#     PWM freq = 1/((K+1)*62.5E-09)
#define HIGH_DUTY   1588    //#     DC = K/PWM_PERIOD
#define LOW_DUTY    250     //#     DC = K/PWM_PERIOD
#define PULSE_LEN   1000ul  //uS    length of high-duty PWM pulse

const uint8_t pinSensor = 2;    //sensor input
const uint8_t pinPWM1 = 5;      //OC3A
const uint8_t pinPWM2 = 6;      //OC4A
const uint8_t pinPWM3 = 46;     //OC5A

const uint8_t pinDbg = 3;       //debug

uint8_t
    nowSensor,
    lastSensor;
volatile bool
    g_bSensorFlag = false;
volatile uint32_t
    g_tStart;

void setup()
{
    //pin 2 (INT4, PE4) captures sensor
    EICRB |= _BV(ISC41) | _BV(ISC40);       //INT4 rising edge
    EIMSK |= _BV(INT4);                     //enable INT4
    
    //set up timers 3, 4 and 5
    //  WGM14 TOP is ICRx -> 1599 gives 10kHz
    //  prescaler == /1    
    //  for WGM14, COMxA1:COMxA0 == 10 OCxA sets on BOTTOM, clears on COMPARE
    TCCR3A = _BV(COM3A1) | _BV(WGM31);
    TCCR3B = _BV(WGM33) | _BV(WGM32) | _BV(CS30);
    ICR3 = PWM_PERIOD;
    OCR3A = LOW_DUTY;
    pinMode( pinPWM1, OUTPUT);

    TCCR4A = _BV(COM4A1) | _BV(WGM41);
    TCCR4B = _BV(WGM43) | _BV(WGM42) | _BV(CS40);
    ICR4 = PWM_PERIOD;
    OCR4A = LOW_DUTY;
    pinMode( pinPWM2, OUTPUT);

    TCCR5A = _BV(COM5A1) | _BV(WGM51);
    TCCR5B = _BV(WGM53) | _BV(WGM52) | _BV(CS50);
    ICR5 = PWM_PERIOD;
    OCR5A = LOW_DUTY;
    pinMode( pinPWM3, OUTPUT);

    pinMode( pinDbg, OUTPUT );
    pinMode( pinSensor, INPUT );
        
}//setup

void loop()
{
    //check if the EXINT on pin 2 set the flag
    //might be wise to wrap this in noInterrupts/interrupts; YMMV
    if( g_bSensorFlag )
    {
        //if so, we're timing the high-duty pulse
        if( (micros() - g_tStart) >= PULSE_LEN )
        {
            //when done, set all outputs back to low-duty...
            OCR3A = LOW_DUTY;
            OCR4A = LOW_DUTY;
            OCR5A = LOW_DUTY;

            //...clear the flag...
            g_bSensorFlag = false;
            
            //...visualize for scoping...
            digitalWrite( pinDbg, LOW );

            //...and re-enable sensor interrupts again
            EIMSK |= _BV(INT4);            
            
        }//if
        
    }//if
 
}//loop

ISR (INT4_vect )
{
    //when we see a rising edge on the sensor pin, grab the time...
    g_tStart = micros();
    
    //...set the three timer outputs to high-duty...
    OCR3A = HIGH_DUTY;
    OCR4A = HIGH_DUTY;
    OCR5A = HIGH_DUTY;
    
    //...visualize for scoping...
    digitalWrite( pinDbg, HIGH );
    
    //...and indicate to the mainline we're timing a pulse
    g_bSensorFlag = true;
    
    //while timing we disable further sensor input interrupts
    EIMSK &= ~(_BV(INT4));  //disable INT4    
    
}//INT4_vect