Mirko Pavleski
Published © GPL3+

Arduino flicker meter-Determining the quality of light bulbs

Numerous studies have shown that flickering, Although high frequency and then totally invisible, It can also cause headaches, eyestrain...

BeginnerFull instructions provided1,925
Arduino flicker meter-Determining the quality of light bulbs

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
Homemade photosensor made of metal transistor
×1
1.3 inch Oled display SH1106
×1
Slide Switch
Slide Switch
×1
Pushbutton Switch, Momentary
Pushbutton Switch, Momentary
×1
Li-Ion Battery 1000mAh
Li-Ion Battery 1000mAh
×2

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Schematic diagram

Code

Arduino code

C/C++
// flicker_meter
//   compute flicker index
// Sketch is for illustrative purposes only  The sketch is  provided as is without any guarantees or warranty or suitability to purpose.
//
// electronupdate@gmail.com
//
//  dependencies:
//  - u8glib required for driving OLED display
//  - Ardunio Nano rev 3
//  - 128 x 64 OLED display. i2c interface... "heltec.cn"
//  - 1 push button switch
//  - Light sensor
//  - extrernal vref

#include "U8glib.h"
#include <Wire.h> //I2C Arduino Library
#include "TimerOne.h"

U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); // I2C / TWI ** this is specific to the OLED panel in use... refer to google's library to select different (huge # of panels supported!)

bool display_mode = 0;   //when in mode zero it shows numeric results, when in mode one, graphically
int processed = 0; // zero if sample buffer consumed otherwise 1
int cycle;
int inPin1 = 12;  
int inPin2 = 11;
int inPin3 = 10;
int button1, button2, button3;
int control_pin = 3;
int i;
int sample_buffer[129];
int sample_pos = 0;
int full_flag = 0;
int sample_min = 1023;
int sample_max = 0;
int min_final = 1023;
int max_final = 0;
int light_sample = 0;
float percent_flicker = 0;
float scale_factor;


void draw(void) {
  // graphic commands to redraw the complete screen should be placed here  
  char temp[50];
  char temp1[50];
  char temp2[50];
  u8g.setFont(u8g_font_unifont);

      percent_flicker = ((max_final - min_final)* 100/(max_final ));

      //noise filter... at really dark levels to prevent error readings of 100% flicker 
       if (min_final<1)                    //if ((max_final - min_final) < 4)
        { percent_flicker = 0;
        }
if (display_mode == 0)
  {
     
  
    // convert numbers into strings so they can  be displayed
      // adriundo or u8g lib never implemented sprintf
      sprintf(temp1,"%d",min_final);
      sprintf(temp2,"%d",max_final);
      dtostrf(percent_flicker,4, 1, temp);
      u8g.drawStr(0,15, "Low:");
      u8g.drawStr(0,27, "High:");
      u8g.drawStr(0,57, "%: ");
      u8g.drawStr(45,15, temp1);
      u8g.drawStr(45,27, temp2);
      u8g.drawStr(45,57,temp);
      sprintf(temp,"%d",display_mode);
      u8g.drawStr(80,15, "Flick.");  
      u8g.drawStr(80,27, "meter");  
      // keyboard check code, uncomment to display key press state
      //if (button1 == 0) {u8g.drawStr(80,10,"1");} else {u8g.drawStr(80,10,"0"); };
      //if (button2 == 0) {u8g.drawStr(90,10,"1");} else {u8g.drawStr(90,10,"0"); };
      //if (button3 == 0) {u8g.drawStr(50,30,"1");} else {u8g.drawStr(50,30,"0"); };
   } 
  
 else
  {
    if (max_final-min_final > 63)
    
    {scale_factor = (float) 63/(max_final - min_final);}
    else 
    {scale_factor = 2;}
    //scale_factor = 1;
    for (i = 0; i < 127; i++)
       {
        u8g.drawPixel(i,(double) (scale_factor * (float)(sample_buffer[i]-min_final)));
     
    }
    

  };  

}

void setup(){
 // some control buttons
  pinMode(inPin1, INPUT_PULLUP);  //delay time down
   pinMode(inPin2, INPUT_PULLUP);  //delay time up
  pinMode(inPin3, INPUT_PULLUP);  // arm system
  pinMode(A0, INPUT);
  
  analogReference( EXTERNAL);
  
  
  Timer1.initialize(100); // timer running at 0.1 ms (i.e. 10KHz sample rate
  Timer1.attachInterrupt (timerIsr); 
      
    //setup oled screen
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255,255,255);
  }
    
}

void timerIsr()
{
  if (processed == 1)
  {
   light_sample = analogRead(0);
   
   sample_buffer[sample_pos] = light_sample;
   
   if (light_sample < sample_min)  sample_min = light_sample;
   if (light_sample >sample_max )  sample_max = light_sample;
   
   sample_pos++;
   
   if (sample_pos == 128)
      { 
        sample_pos =0;
        min_final = sample_min;
        max_final = sample_max;
        
        sample_min = 1023;
        sample_max = 0;
        processed = 0;  // set a flag telling main routine there is a data set to process
      }
   
  }

}


void loop(){
  
// inint oled

  
  button1 = digitalRead(inPin1);
  button2 = digitalRead(inPin2);
  button3 = digitalRead(inPin3);  

  if (button1 == 0) { display_mode = display_mode ^ 1; 
             delay(100);
           } // toggle between numeric and graphic  

  u8g.firstPage();      
   do { 
            draw();
     
      }  while( u8g.nextPage() );

processed = 1;
 delay(100);  
   
}

Credits

Mirko Pavleski

Mirko Pavleski

116 projects • 1163 followers

Comments