frenchy22
Published © GPL3+

A Serious Stroboscope

This stroboscope is a precise and versatile instrument which can be used to analyze periodic or fast motions.

IntermediateFull instructions provided3,730
A Serious Stroboscope

Things used in this project

Hardware components

Arduino Nano Every
Arduino Nano Every
×1
Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
Any standard 16x2 alphanumeric LCD with backlight and compatible with liquidCrystal library
×1
Pushbutton 6 mm
×4
Single Turn Potentiometer- 10k ohms
Single Turn Potentiometer- 10k ohms
×2
Small Signal Diode, Switching
Small Signal Diode, Switching
Any model such as 1N914, 1N4148...
×1
Logic Level FET N-Channel
Logic Level FET N-Channel
2 mandatory, 1 optional
×3
Resistor 47 ohms 1 W
×1
Resistor (value depending of the LCD backlight)
See text and table about LCD backlight to determine the value of R1
×1
9 LED torch
4.5 V power supply, usually 3 x 1.5 batteries
×1
Electronic flash
Optional. Any electronic flash with a short recycling time
×1
Flash adapter
Optional
×1
3.5 mm female jack plug mono
Optional
×1
9V battery (generic)
9V battery (generic)
×1
9V Battery Clip
9V Battery Clip
×1
Solderless Breadboard Full Size
Solderless Breadboard Full Size
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Schematic diagram

Circuit

Code

Untitled file

C/C++
[code]
                  
              /* A serious stroboscope */

       /*------------ The hardware ------------ */
/*
This stroboscope uses a standard 16x2 Liquid Crystal Display
It is connected in the same way as in the examples of the
LiquidCrystal library, except for the backlight whose brightness
can be adjusted by a potentiometer (P1). This potentiometer
delivers a 0 - 5 V voltage to the analog input A7, and the LED- 
pin of the backlight is driven by the PWM output pin D10 through
an N-channel MOSFET (Q1) and a resistor (R1). The LED+ pin of
the backlight is connected to the 9V power supply.
*/
#include <LiquidCrystal.h>

/*
Initialize the library by associating any needed LCD interface
pin with the arduino pin number it is connected to
*/
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int backLightPotPin=A7;
const int backLightPin=10;

/* 
The period and the duration of the flash can be adjusted via
four pushbuttons PB0 to PB4 which are connected to the pins
D6 - D9 of the arduino. 
*/
const int pushButtonPin[4]={6, 7, 8, 9};

/*
The flash is delivered by a 9 LEDs torch whose cathode is
connected to the pin D13 of the arduino through an N-channel
MOSFET (Q2) and a 47 ohms 1 W resistor (R2).
The anode of the LED torch is connected to the 9V power supply.
*/
const int ledPin=13;

/*
Optionally, the stroboscope can drive an electronic flash whose
central contact is connected to the A6 pin through an N-channel
MOSFET (Q3).
*/
const int electronicFlashPin=A6;

/*
The stroboscope can be synchronized by connecting the pin A5 to
the ground.
*/
const int synchroPin=A5;


     /* ------ The constants and global variables ------ */
    
/*
Characteristics of the flash in microseconds,
resolution 100 microseconds
*/
unsigned long flashPeriod=500000, flashDuration=100000;

/*
Measurement of elapsed time to control the flash
*/
unsigned long lastTime=0, actualTime, elapsed;

/*
Management of the pushbuttons : each pushbutton increases or
decreases one of the values of the flash, and when the button
is pressed during some seconds, the value increases or decreases
faster and faster.
These constants determine the behaviour of the pushbuttons.

After "debounceTime" (50 ms), the value is increased or
decreased once by 100 microsec. and the flag "incremented" is
set to true to remind it.

After "firstDelayButton" (1000 ms), the value is increased or
decreased by "firstIncrementButton" (100 microsec.) every
"firstRepeatButton" (300 ms).

After "secondDelayButton" (4000 ms), the value is increased or
decreased by "secondIncrementButton" (100 microsec.) every
"secondRepeatButton" (50 ms).

After "thirdDelayButton" (8000 ms), the value is increased or
decreased by "thirdIncrementButton" (10000 microsec.) every
"thirdRepeatButton" (200 ms).

You are encouraged to modify these values in order to adapt the
behaviour of the pushbuttons to your own comfort.
*/

const unsigned firstDelayButton=1000,
               firstIncrementButton=100,
               firstRepeatButton=300,
               secondDelayButton=4000,
               secondIncrementButton=100,
               secondRepeatButton=50,
               thirdDelayButton=8000,
               thirdIncrementButton=10000,
               thirdRepeatButton=200;

const unsigned debounceDelay=50;
bool incremented=false;

/*
Global variables for the management of the pushbuttons :
*/
int pressedButton;                 // The number of the
                                   // pushbutton being pressed

unsigned long actualButtonsTime=0; // The actual time in ms for
                                   // the management of the
                                   // pushbuttons

unsigned long buttonPressedTime=0; // The time at which a button
                                   // has been pressed

unsigned long elapsedButton;       // The time since a button is
                                   // beeing pressed

unsigned long incrementTime=0;     // The time at which the 
                                   // value has been increased
                                   // or decreased last.

unsigned long incrementDelay=0;    // The time since the value
                                   // has been increased
                                   // or decreased last.

/* ------------ The functions ------------ */

void displayValues()
/*
Display the period and the duration of the flash in ms and
tenth of ms.
 */
{
  int displayedPeriod = flashPeriod/100;
  int displayedDuration = flashDuration/100;

// Display the period on the LCD
  lcd.setCursor(6, 0);
  if (displayedPeriod < 100)
    lcd.print(" ");
  if (displayedPeriod < 1000)
    lcd.print(" ");
  lcd.print(displayedPeriod/10);
  lcd.setCursor(10,0);
  lcd.print(displayedPeriod-10*(displayedPeriod/10));
  
// Display the duration on the LCD
  lcd.setCursor(6, 1);
  if (displayedDuration < 100)
    lcd.print(" ");
  if (displayedDuration < 1000)
    lcd.print(" ");
  lcd.print(displayedDuration/10);
  lcd.setCursor(10,1);
  lcd.print(displayedDuration-10*(displayedDuration/10));
}

bool readButtons()
/* 
Returns true if one of the four pushbuttons is pressed.
The number of the pressed button is copied into the global
variable "pressedButton".
*/
{
  for (int i=0; i<4; i++)
    if (digitalRead(pushButtonPin[i])==LOW)
    {
      pressedButton=i;
      return(true);
    }
  return(false);
}

void increaseDecrease(int increment)
/* 
According to the pressed pushbutton, the value of "increment" is
added or substracted to the period or the duration of the flash.
The values are limited from 0.1 to 999.9 ms.
*/
{
  switch(pressedButton)
  {
    case 0 :
      if (flashPeriod < 999900-increment)
        flashPeriod+=increment;
      else flashPeriod=999900;
      break;
    case 1 :
      if (flashPeriod > 100+increment)
        flashPeriod-=increment;
      else flashPeriod=100;
      break;
    case 2 :
      if (flashDuration < 999900-increment)
        flashDuration+=increment;
      else flashDuration=999900;
      break;
    case 3 :
      if (flashDuration > 100+increment)
        flashDuration-=increment;
      else flashDuration=100;
      break;
  }
  displayValues();
}

void manageIncrementTime(int delayValue, int increment)
/* 
Manage the delay between increasing or decreasing the flash
values. When "incrementDelay" reaches "delayValue", the function
"increaseDecrease" is called.
*/
{
  if (actualButtonsTime < incrementTime)
    incrementDelay=0xFFFFFFFFul-incrementTime+actualButtonsTime;
  else
    incrementDelay=actualButtonsTime-incrementTime;    
  if (incrementDelay>=delayValue)
  {
    increaseDecrease(increment);
    incrementTime=actualButtonsTime;
  }
}

void setup() {
  // put your setup code here, to run once:
for (int i=0; i<4; i++) pinMode(pushButtonPin[i], INPUT_PULLUP);
pinMode(backLightPin, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(electronicFlashPin, OUTPUT);
pinMode(synchroPin, INPUT_PULLUP);
digitalWrite(ledPin, LOW);
digitalWrite(electronicFlashPin, LOW);

// set up the LCD's number of columns and rows:
lcd.begin(16, 2);

// display fix characters on the LCD
lcd.setCursor(1, 0);
lcd.print("Per.    .  ms");
lcd.setCursor(1, 1);
lcd.print("Dur.    .  ms");
displayValues();
}

void loop() {
  // put your main code here, to run repeatedly:

/* 
Turn on and off the LED torch when necessary. Generate a pulse
towards the electronic flash when the flash period is elapsed.
*/
digitalWrite(electronicFlashPin, LOW);
actualTime=micros();

if (digitalRead(synchroPin)==LOW) // Stop flash when synchro is
                                  // grounded
{
  lastTime=actualTime;
  digitalWrite(ledPin, LOW);
}
else
{
  if (actualTime < lastTime)
    elapsed=0xFFFFFFFFul-lastTime+actualTime;
  else
    elapsed=actualTime-lastTime;
  if (elapsed>=flashDuration) digitalWrite(ledPin, LOW);
  if (elapsed>=flashPeriod)
  {
    digitalWrite(ledPin, HIGH);
    digitalWrite(electronicFlashPin, HIGH);
    lastTime+=flashPeriod;
  }

/*
Manage the pushbuttons. According to the time since a button
has been pressed, the function "manageIncrementTime" is called.
*/
actualButtonsTime=millis();
if (readButtons())
{
  if (actualButtonsTime<buttonPressedTime)
    elapsedButton=0xFFFFFFFFul-buttonPressedTime
                              +actualButtonsTime;
  else
    elapsedButton=actualButtonsTime-buttonPressedTime;
  if (elapsedButton>thirdDelayButton)
    manageIncrementTime(thirdRepeatButton, 
                        thirdIncrementButton);
  else if (elapsedButton>secondDelayButton)
    manageIncrementTime(secondRepeatButton,
                        secondIncrementButton);
  else if (elapsedButton>firstDelayButton)
    manageIncrementTime(firstRepeatButton,
                        firstIncrementButton);
  else if (elapsedButton>debounceDelay & !incremented)
  {
    increaseDecrease(100);
    incremented=true;
  }
}
else
{
  buttonPressedTime=actualButtonsTime;
  incremented=false;
}

/*
Adjust the brightness of the backlight of the LCD according
to the position of the potentiometer.
*/
analogWrite(backLightPin, analogRead(backLightPotPin)/4);
}
}
[/code]

Credits

frenchy22

frenchy22

6 projects • 3 followers

Comments