Pulsing 2 leds at specefic intervals for stroboscopic effect

Hey.

So im trying to make a differential stroboscope. I wrote a code based on a research paper i saw on google, but the thing is, I dont know what to expect from it. I am an not an avid coder, so its quite hard for me. but i did my best. I dont have an oscilloscope to test things out, and its gonna be a few more days till i get my hands on the hardware of this project. This is what im actually trying to do.

#include <avdweb_AnalogReadFast.h>
#include <digitalWriteFast.h>
//basic libraries for faster read and write
#define greenPulse 5
#define redPulse 6
#define potentiometer 3
#define switchUp 7
#define switchDown 8
//the libraries prefers the pins to be defined.

int minimum_Time_Between_Pulse = 1;
//An upper and lower limit so the potentiometer value can be mapped.Not sure if it can be done without.
int maximum_Time_Between_Pulse = 50;

int pulseDuration=50;//the duration of the time the led stayes on
int timeBetweenPulse;
//variables
int timeBetweenPulseActual;

void setup()
{
pinModeFast(greenPulse, OUTPUT);
pinModeFast(redPulse, OUTPUT);//as simple as that. or is it?
pinModeFast(potentiometer, INPUT);
pinMode(switchUp, INPUT_PULLUP);//didnt find a pullup function in library
pinMode(switchDown, INPUT_PULLUP);

}


void loop()
{
timeBetweenPulse = map(analogRead(potentiometer), 0, 1024,minimum_Time_Between_Pulse, maximum_Time_Between_Pulse);// Map the potentiometer value.
timeBetweenPulseActual = timeBetweenPulse;// timeBetweenPulse is from the potentiometer, so it seems like a constant to me, which probably isnt tweakable while the pot is connected
while(switchUp == LOW && timeBetweenPulseActual <= maximum_Time_Between_Pulse)// increase the pulse time while the button is pressed
{
  ++timeBetweenPulseActual;//increase
}
while(switchDown == LOW && timeBetweenPulseActual >= minimum_Time_Between_Pulse)//same as before, to decrease
{
  --timeBetweenPulseActual;
}
digitalWriteFast(greenPulse, HIGH);//The first pulse
delayMicroseconds(pulseDuration);//on during pulse duration
digitalWriteFast(greenPulse, LOW);//as soon as time runs out
delay(timeBetweenPulseActual/2);// delays are blocking, so no way i can turn the other led on,plus this gives me the other pulse at exact half time
digitalWriteFast(redPulse, HIGH);//same as before, the second pulse
delayMicroseconds(pulseDuration);//as before
digitalWriteFast(redPulse, LOW);
delay(timeBetweenPulseActual/2);//rest of the delay
}

please leave your thoughts on the code, its pretty frustrating to spend 3 hours on something and waiting a week just find out its garbage/..

Thanks

How fast should it blink ? In the MegaHerz range ? If not, then please use normal Arduino functions.

How accurate should be blinking be ? Is it allowed that a interrupt makes something tens of microseconds longer ?

You forgot to mention what the potentiometer should do. Is the time that the leds are ‘on’ always the same ? so the potentiometer only determines the Toff ?

You are going to have a problem using the buttons to 'tweak' the time between pulses because every time you go through loop() you are resetting the value based on the potentiometer input. One way to fix that is to keep separate values for the potentiometer and the buttons and modify them separately. Then add them together to use as the actual value.

Koepel:
How fast should it blink ? In the MegaHerz range ? If not, then please use normal Arduino functions.

How accurate should be blinking be ? Is it allowed that a interrupt makes something tens of microseconds longer ?

You forgot to mention what the potentiometer should do. Is the time that the leds are ‘on’ always the same ? so the potentiometer only determines the Toff ?

The more accurate the better, but i would choose simplicity over overtly complex code.

say something spins at 50,000 RPM, so it makes about 833.33 spins a second. By formula of f=1/T, which gives us 1 spin at .0012 seconds, 1.2 milliseconds.

I doubt im going to find something faster than 50000 rpm at home. so thats the fastest the led has to blink.

given that a microsecond is a thousandth of a millisecond, no it shouldnt be a problem.

The potentiometer is there so you can get to a rough value , from which you can fine tune with the buttons. The led on/ Ton is constant and set in the code. The only modifiable value is the Toff

The reason i felt uncomfortable with normal functions is because of the second pulse. I am pretty doubtful about if this is going to actually work at all.

with each digitalWrite, the timing gets pushed behind a bit. So by the time the greenPulse has to go high , wont it make a considerable difference? or am i worrying too much?

johnwasser:
You are going to have a problem using the buttons to ‘tweak’ the time between pulses because every time you go through loop() you are resetting the value based on the potentiometer input. One way to fix that is to keep separate values for the potentiometer and the buttons and modify them separately. Then add them together to use as the actual value.

Should i use interrupts? as this code basically breathes in delays, wont there be a higher chance that a considerable amount of pulses to be missed while pressing buttons? or should i get rid of the potentiometer altogether?

You can program timers to do this, but you'll need to understand the details of the timer hardware.

With two pins driven from the same timer you can use one inverted with a large duty cycle and the other
non-inverted with a small duty cycle. So long as a phase-correct mode is used that will give you the
interleaved pulses you want.

what do you think about the range being between 30 RPM to 50000 RPM? so about 2000 milliseconds to 1.2 milliseconds? Should i use Decimal numbers instead of integer for the delay?

MarkT:
You can program timers to do this, but you'll need to understand the details of the timer hardware.

With two pins driven from the same timer you can use one inverted with a large duty cycle and the other
non-inverted with a small duty cycle. So long as a phase-correct mode is used that will give you the
interleaved pulses you want.

I would prefer not to use timers and lower level code. I find them simply too complicated and have really bad understanding of the timer hardware.

But is it a must use/ must have in this case?>

I made a few edits based on the suggestions. Is it better now?

#include <avdweb_AnalogReadFast.h>
#include <digitalWriteFast.h>
//basic libraries for faster read and write
#define greenPulse 5
#define redPulse 6
#define potentiometer 3
#define switchUp 7
#define switchDown 8
//the libraries prefers the pins to be defined.
//minimum time and maximum time comes from formula f=1/T, hence theoretically, this can reach Upto 60,000 RPM, Its very possible to get to much much MUCH higher value just by using microseconds instead of millis
float minimum_Time_Between_Pulse = 1;
//An upper and lower limit so the potentiometer value can be mapped.Not sure if it can be done without.
float maximum_Time_Between_Pulse = 20000;

int pulseDuration=50;//the duration of the time the led stayes on in microseconds
float timeBetweenPulse;
//variables
float timeBetweenPulseActual;
float fineTune = 0;

void setup()
{
pinModeFast(greenPulse, OUTPUT);
pinModeFast(redPulse, OUTPUT);//as simple as that. or is it?
pinModeFast(potentiometer, INPUT);
pinMode(switchUp, INPUT_PULLUP);//didnt find a pullup function in library
pinMode(switchDown, INPUT_PULLUP);

}


void loop()
{  
timeBetweenPulse = map(analogRead(potentiometer), 0, 1024,minimum_Time_Between_Pulse, maximum_Time_Between_Pulse);// Map the potentiometer value.
//faulty, resets everytime the loop() is run//timeBetweenPulseActual = timeBetweenPulse;// timeBetweenPulse is from the potentiometer, so it seems like a constant to me, which probably isnt tweakable while the pot is connected
if(switchUp == LOW && switchDown == LOW)
{
  //do Nothing
}

else{
while(switchUp == LOW && timeBetweenPulseActual <= maximum_Time_Between_Pulse)// increase the pulse time while the button is pressed
{
  //timeBetweenPulseActual + 0.01; //test purpose
  fineTune + 0.1 ;//increase
}
while(switchDown == LOW && timeBetweenPulseActual >= minimum_Time_Between_Pulse)//same as before, to decrease
{
  //timeBetweenPulseActual - 0.01;//test purpose
  fineTune - 0.1;
}
timeBetweenPulseActual = timeBetweenPulse + fineTune;
while(timeBetweenPulseActual > maximum_Time_Between_Pulse)
{
  timeBetweenPulseActual = maximum_Time_Between_Pulse;
}

while(timeBetweenPulseActual < minimum_Time_Between_Pulse)
{
  timeBetweenPulseActual = minimum_Time_Between_Pulse;
}

digitalWriteFast(greenPulse, HIGH);//The first pulse
delayMicroseconds(pulseDuration);//on during pulse duration
digitalWriteFast(greenPulse, LOW);//as soon as time runs out
delay(timeBetweenPulseActual/2);// delays are blocking, so no way i can turn the other led on,plus this gives me the other pulse at exact half time
digitalWriteFast(redPulse, HIGH);//same as before, the second pulse
delayMicroseconds(pulseDuration);//as before
digitalWriteFast(redPulse, LOW);
delay(timeBetweenPulseActual/2);//rest of the delay
}
}

I maybe wrong, but the previous code seemed like it imposed no lower/upper limit if the buttons were pressed for long enough to surpass the time

while(switchUp == LOW && timeBetweenPulseActual <= maximum_Time_Between_Pulse)// increase the pulse time while the button is pressed

{
  //timeBetweenPulseActual + 0.01; //test purpose
  fineTune + 0.1 ;//increase
}
while(switchDown == LOW && timeBetweenPulseActual >= minimum_Time_Between_Pulse)//same as before, to decrease
{
  //timeBetweenPulseActual - 0.01;//test purpose
  fineTune - 0.1;
}
timeBetweenPulseActual = timeBetweenPulse + fineTune;

timeBetweenPulseActual is calculated After the while statements, so how can the while statement check something that isnt there?

#define greenPulse 5
#define redPulse 6
#define potentiometer 3
#define switchUp 7
#define switchDown 8
//the libraries prefers the pins to be defined.
//minimum time and maximum time comes from formula f=1/T, hence theoretically, this can reach Upto 60,000 RPM, Its very possible to get to much much MUCH higher value just by using microseconds instead of millis
float minimum_Time_Between_Pulse = 0;
//An upper and lower limit so the potentiometer value can be mapped.Not sure if it can be done without.
float maximum_Time_Between_Pulse = 20001;

int pulseDuration=50;//the duration of the time the led stayes on in microseconds
float timeBetweenPulse;
//variables
float timeBetweenPulseActual;
float fineTune = 0;

void setup()
{
pinMode(greenPulse, OUTPUT);
pinMode(redPulse, OUTPUT);//as simple as that. or is it?
pinMode(potentiometer, INPUT);
pinMode(switchUp, INPUT_PULLUP);//didnt find a pullup function in library
pinMode(switchDown, INPUT_PULLUP);
Serial.begin(200000);
}


void loop()
{  
timeBetweenPulse = map(analogRead(potentiometer), 0, 1024,minimum_Time_Between_Pulse, maximum_Time_Between_Pulse);// Map the potentiometer value.
//faulty, resets everytime the loop() is run//timeBetweenPulseActual = timeBetweenPulse;// timeBetweenPulse is from the potentiometer, so it seems like a constant to me, which probably isnt tweakable while the pot is connected
if(switchUp == LOW && switchDown == LOW)
{
  //do Nothing
}

else{
while(switchUp == LOW && timeBetweenPulseActual <= maximum_Time_Between_Pulse)// increase the pulse time while the button is pressed
{
  //timeBetweenPulseActual + 0.01; //test purpose
  fineTune + 0.1 ;//increase
}
while(switchDown == LOW && timeBetweenPulseActual >= minimum_Time_Between_Pulse)//same as before, to decrease
{
  //timeBetweenPulseActual - 0.01;//test purpose
  fineTune - 0.1;
}
timeBetweenPulseActual = timeBetweenPulse + fineTune;
while(timeBetweenPulseActual > maximum_Time_Between_Pulse)
{
  timeBetweenPulseActual = maximum_Time_Between_Pulse;
}

while(timeBetweenPulseActual < minimum_Time_Between_Pulse)
{
  timeBetweenPulseActual = minimum_Time_Between_Pulse;
}
Serial.println(timeBetweenPulseActual);
digitalWrite(greenPulse, HIGH);//The first pulse
delayMicroseconds(pulseDuration);//on during pulse duration
digitalWrite(greenPulse, LOW);//as soon as time runs out
delay(timeBetweenPulseActual/2);// delays are blocking, so no way i can turn the other led on,plus this gives me the other pulse at exact half time
digitalWrite(redPulse, HIGH);//same as before, the second pulse
delayMicroseconds(pulseDuration);//as before
digitalWrite(redPulse, LOW);
delay(timeBetweenPulseActual/2);//rest of the delay
}
}

The pushbuttons still dont work…

Which Arduino board are you using ?

The potentiometer should only be accepted when it changes. When no one touches the potentiometer, then the value returned by analogRead() is not 100% perfect steady, because there is probably some noise. You can not do precise turning with the potentiometer and use the buttons at the same time.

Koepel:
Which Arduino board are you using ?

The potentiometer should only be accepted when it changes. When no one touches the potentiometer, then the value returned by analogRead() is not 100% perfect steady, because there is probably some noise. You can not do precise turning with the potentiometer and use the buttons at the same time.

I am using an arduino nano

do you mean i cant use buttons and the potentiometer 'phisically' together? or do you mean that i have to either use a pot or the buttons?

I mean in the sketch. When no one touches the potentiometer, the analogRead() can still return small variations because of noise.

You can turn off the potentiometer as soon as a button is pressed. Then you need something to be able to use the potentiometer again, for example pressing both buttons at the same time or when the potentiometer is turned a certain amount. That makes a the sketch larger and more complex. That is the way it is. Sometimes it is easy to explain what it should do, but in the sketch it is a whole lot of code.

Koepel:
You can turn off the potentiometer as soon as a button is pressed. Then you need something to be able to use the potentiometer again, for example pressing both buttons at the same time

I was thinking along the same lines but I didn’t think of the “Push both to use Potentiometer”. That should be a viable solution. If you hold down both buttons you can turn the knob to get a rough setting. Then you can use the buttons separately to tweak up or down. Here is some code to do that:

void loop()
{
  // This goes outside the 'if' to keep the loop frequency more consistent
  int analogValue = analogRead(potentiometer);
  timeBetweenPulse = map(analogValue, 0, 1024, minimum_Time_Between_Pulse, maximum_Time_Between_Pulse);


  if (digitalRead(switchUp) == LOW && digitalRead(switchDown) == LOW)
  {
    // Use the value from the potentiometer if both buttons are pressed
    timeBetweenPulseActual = timeBetweenPulse;
  }
  else if (digitalRead(switchUp) == LOW)
  {
    // increase the pulse time while the UP button is pressed
    if (timeBetweenPulseActual < maximum_Time_Between_Pulse)
      ++timeBetweenPulseActual; //increase
  }
  else if (switchDown == LOW)
  {
    // decrease the pulse time while the DOWN button is pressed
    if (timeBetweenPulseActual > minimum_Time_Between_Pulse
        --timeBetweenPulseActual;
  }


digitalWrite(greenPulse, HIGH); //The first pulse
  delayMicroseconds(pulseDuration);//on during pulse duration
  digitalWrite(greenPulse, LOW);//as soon as time runs out


  delay(timeBetweenPulseActual / 2);


  digitalWrite(redPulse, HIGH);//same as before, the second pulse
  delayMicroseconds(pulseDuration);//as before
  digitalWrite(redPulse, LOW);


  delay(timeBetweenPulseActual / 2); //rest of the delay
}

johnwasser:
I was thinking along the same lines but I didn’t think of the “Push both to use Potentiometer”. That should be a viable solution. If you hold down both buttons you can turn the knob to get a rough setting. Then you can use the buttons separately to tweak up or down. Here is some code to do that:

void loop()

{
  // This goes outside the ‘if’ to keep the loop frequency more consistent
  int analogValue = analogRead(potentiometer);
  timeBetweenPulse = map(analogValue, 0, 1024, minimum_Time_Between_Pulse, maximum_Time_Between_Pulse);

if (digitalRead(switchUp) == LOW && digitalRead(switchDown) == LOW)
  {
    // Use the value from the potentiometer if both buttons are pressed
    timeBetweenPulseActual = timeBetweenPulse;
  }
  else if (digitalRead(switchUp) == LOW)
  {
    // increase the pulse time while the UP button is pressed
    if (timeBetweenPulseActual < maximum_Time_Between_Pulse)
      ++timeBetweenPulseActual; //increase
  }
  else if (switchDown == LOW)
  {
    // decrease the pulse time while the DOWN button is pressed
    if (timeBetweenPulseActual > minimum_Time_Between_Pulse
        --timeBetweenPulseActual;
  }

digitalWrite(greenPulse, HIGH); //The first pulse
  delayMicroseconds(pulseDuration);//on during pulse duration
  digitalWrite(greenPulse, LOW);//as soon as time runs out

delay(timeBetweenPulseActual / 2);

digitalWrite(redPulse, HIGH);//same as before, the second pulse
  delayMicroseconds(pulseDuration);//as before
  digitalWrite(redPulse, LOW);

delay(timeBetweenPulseActual / 2); //rest of the delay
}

Thanks! Ill do some testing and get back…

johnwasser:

else if (digitalRead(switchUp) == LOW)

{
    // increase the pulse time while the UP button is pressed
    if (timeBetweenPulseActual < maximum_Time_Between_Pulse)
      ++timeBetweenPulseActual; //increase
  }
  else if (switchDown == LOW)
  {
    // decrease the pulse time while the DOWN button is pressed
    if (timeBetweenPulseActual > minimum_Time_Between_Pulse
        --timeBetweenPulseActual;
  }

Wont this make the code increase/decrease by 1 per cycle the loop is run? I need the code to increase by .01 or .1, so when i do that, wont it make the increase decrease REALLY slow?

What im basically asking is, Using the above code, With the if statement, can the code run reliably and fast enough?

kaseftamjid:
Should i use Decimal numbers instead of integer for the delay?

Almost certainly not. Decimals are very slowing 8 bit processors with little to no hardware maths acceleration.
If you need more accuracy (1 dp for example) store your values with as integers with an implied decimal point:
10 = 1.0
11 = 1.1
etc

Even better, store with a fractional component that is a power of 2. e.g. 256.
Now you can get the integer part with a simple n bit shift right.

kaseftamjid:
Wont this make the code increase/decrease by 1 per cycle the loop is run? I need the code to increase by .01 or .1, so when i do that, wont it make the increase decrease REALLY slow?

Slower, yes. Only you can say if it is too slow.

What im basically asking is, Using the above code, With the if statement, can the code run reliably and fast enough?

Isn’t the only use for timeBetweenPulseActual as an I put to the delay function?
You do realise that only takes an integer value?
So having a decimal is pointless.....

If you want any accuracy with this at all you need to stop using delay and start to timing delays with millis() or micros().

should i use analog smoothing to get rid of adc noice? theres a library available for that..

umm. One more thing , Given what im trying to do,

digitalWrite(greenPulse, HIGH); //The first pulse
  delayMicroseconds(pulseDuration);//on during pulse duration
  digitalWrite(greenPulse, LOW);//as soon as time runs out


  delay(timeBetweenPulseActual / 2);


  digitalWrite(redPulse, HIGH);//same as before, the second pulse
  delayMicroseconds(pulseDuration);//as before
  digitalWrite(redPulse, LOW);


  delay(timeBetweenPulseActual / 2); //rest of the delay

Is this part okay? Im going for control over 1-10th of a millisecond, so is this usable?

pcbbc:
Almost certainly not. Decimals are very slowing 8 bit processors with little to no hardware maths acceleration.
If you need more accuracy (1 dp for example) store your values with as integers with an implied decimal point:
10 = 1.0
11 = 1.1
etc

Even better, store with a fractional component that is a power of 2. e.g. 256.
Now you can get the integer part with a simple n bit shift right.

pcbbc:
Almost certainly not. Decimals are very slowing 8 bit processors with little to no hardware maths acceleration.
If you need more accuracy (1 dp for example) store your values with as integers with an implied decimal point:
10 = 1.0
11 = 1.1
etc

Even better, store with a fractional component that is a power of 2. e.g. 256.
Now you can get the integer part with a simple n bit shift right.

I actually meant float.. But does this still apply for floating points?