Driver for Diving Flashlite

Hi,

i am markus from Germany. my actual Project is to build up a dive light with a blue and some White high power leds. i´m an electronic engineer, so build up the electronics is no Problem. i build several flashlites at the past. you can see some at my Homepage. but now back to my Project with some Details about it:

  • flashlite Body with magnetic push button (hall) is here
  • 3 x cree xm-l high cri are here
  • 1 x quad die blue led is here
  • 2 x constand current Regulators with pwm Input are here

now i need a µc and some Software to realize the on/off/switching. the mode switching should be done with the original hall push button. so after 5 presses the fglashlite should be off again:

  • ...off
  • White on 30% (blue off)
  • White on 75 % (blue off)
  • White on 100% (blue off)
  • blue on 100% (White off)
  • off....

i have started to read about µc and i think the arduino Plattform will be good for this. i am no programmer but i will learn about it. so i startet to write some code. most of it is used from an exampe (pushbutton):

const int ledPinwhite = 9;  // white LED
const int ledPinblue = 10;  // blue LED
const int hallPin = 11;    // the number of the input pin

int state = LOW;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers

void setup()
{
  pinMode(hallPin, INPUT);
  pinMode(ledPinblue, OUTPUT);
  pinMode(ledPinwhite, OUTPUT);
}

void loop()
{
  reading = digitalRead(hallPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (ledPinwhite == 0 && ledPinblue == 0)
    {
      analogWrite(ledPinwhite,64);
    }
    if (ledPinwhite == 64 && ledPinblue == 0)
    {
      analogWrite(ledPinwhite,128);
    }
    if (ledPinwhite == 128 && ledPinblue == 0)
    {
      analogWrite(ledPinwhite,254);
    }
    if (ledPinwhite == 254 && ledPinblue == 0)
    {
      analogWrite(ledPinwhite,0);
      analogWrite(ledPinblue,255);
    }
    if (ledPinwhite == 0 && ledPinblue == 255)
    {
      analogWrite(ledPinblue,0);
    }    

    time = millis();    
  }
    
  previous = reading;
}

I hope my the arduino uno Hardware will arrive today so i can test this code. what do you think about it? will this work? my Goals are:

  • bring the switching mode code to work
  • implement a function that locks the light after 3 short presses & unlock the lite with 3 short presses again
  • implement power Management functions when light is locked
  • implement a battery Monitoring function so the led will flicker 1 time every Minute and rampd down the brightness

hope i get some help from you.

markus

  pinMode(hallPin, INPUT);

You have a hall attached to the pin?

Are you using an external resistor with that hall? Why? The Arduino has a perfectly good built in one that you are not using.

    if (ledPinwhite == 0 && ledPinblue == 0)

Given that these are constants, and do not have those values, it seems unlikely that this will ever be true.

    if (ledPinwhite == 64 && ledPinblue == 0)
    if (ledPinwhite == 128 && ledPinblue == 0)
    if (ledPinwhite == 254 && ledPinblue == 0)
    if (ledPinwhite == 0 && ledPinblue == 255)

Or any of these.

Hi,

i painted a short shematic:

i think the hall doesn´t need a external resistor. it Needs 5 Volt at the Input and give a low on Output. when the magnet is near the Output will Switch from low to high.

    if (ledPinwhite == 0 && ledPinblue == 0)

my idea was to use the if cause i must inluce the hall and the state of the leds. so if the hall give a high and both leds are of then the light have to Switch to the first mode. but you are right the leds are set to low in Initial state! so this seem better for me:

  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    {
      analogWrite(ledPinwhite,64);
    }
    if (ledPinwhite == 64 && ledPinblue == 0)
    {
      analogWrite(ledPinwhite,128);
    }
    if (ledPinwhite == 128 && ledPinblue == 0)
    {
      analogWrite(ledPinwhite,254);
    }
    if (ledPinwhite == 254 && ledPinblue == 0)
    {
      analogWrite(ledPinwhite,0);
      analogWrite(ledPinblue,255);
    }
    if (ledPinwhite == 0 && ledPinblue == 255)
    {
      analogWrite(ledPinblue,0);
    }

markus

my idea was to use the if cause i must inluce the hall

You must what?

so this seem better for me:

Lets see. We'll substitute the values that are known for the variables:

  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    {
      analogWrite(9,64);
    }
    if (9 == 64 && 10 == 0)
    {
      analogWrite(9,128);
    }
    if (9 == 128 && 10 == 0)
    {
      analogWrite(9,254);
    }
    if (9 == 254 && 10 == 0)
    {
      analogWrite(9,0);
      analogWrite(10,255);
    }

Now, does that make sense?

Hi,

sorry for my bad english...i will try again to explain my idea:
the lamp starts with both leds of (Initial state). now i press the button and the Output of the White should be 1/4 pwm:

  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    {
      analogWrite(ledPinwhite,64);
    }

to get into the next mode on the next press of the button (pwm 128 of White) i use this:

    if (ledPinwhite == 64 && ledPinblue == 0)
    {
      analogWrite(ledPinwhite,128);
    }

for me this makes sense, but i am not a programmer :drooling_face:

const int ledPinwhite = 9;  // white LED
if (ledPinwhite == 64 && ledPinblue == 0)

Now do you see the problem?

Hi,

i have rewritten the code a little bit:

int whiteledPin = 9;  // pin 9 has the white led connected
int blueledPin = 10;  // pin 10 has the blue led connected
int hallPin = 11;    // pin 11 has the hall sensor connected

void setup() {                
  // initialize the pins as output/input and set output to 0
  pinMode(whiteledPin, OUTPUT);
  pinMode(blueledPin, OUTPUT);
  pinMode(hallPin, INPUT);
  analogWrite(whiteledPin,0)
  digitalWrite(blueledPin, LOW);
  
}

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers

void loop()
{
  reading = digitalRead(hallPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    {
      analogWrite(whiteledPin,64);
    }
    if (whiteledPin == 64 && blueledPin == 0)
    {
      analogWrite(ledPinwhite,128);
    }
    if (whiteledPin == 128 && blueledPin == 0)
    {
      analogWrite(ledPinwhite,254);
    }
    if (whiteledPin == 254 && blueledPin == 0)
    {
      analogWrite(whiteledPin,0);
      analogWrite(blueledPin,255);
    }
    if (whiteledPin == 0 && blueledPin == 255)
    {
      analogWrite(blueledPin,0);
    }    

    time = millis();    
  }
    
  previous = reading;
}

but now i see a other problem. when the button is pressed the output will be set to:

  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    {
      analogWrite(whiteledPin,64);

but the next press will also set it only to:

analogWrite(whiteledPin,64)

right?

other question. is it possible to read out the pwm state of an anlog output like this?

if (whiteledPin == 64 && blueledPin == 0)

Ok, now i read some more about reading states, so my code will not work. my intention was to read the status (pwm 128) of the output pins as:

    if (whiteledPin == 128 && blueledPin == 0)

then set the output to the next mode (pwm 254):

 analogWrite(ledPinwhite,254

but now i know that this will not work.

Now i need a idea how to switch to the next mode...

thanks, markus

Why would you want to read a PWM pin?
Its value won't have changed from the value you last wrote to it (hint)

    switch (state)
    {
      case 0:
        whiteLevel = 0;
        blueLevel = 0;
      break;
      case 1:
        whiteLevel = (30 * 255) / 100;
        blueLevel = 0;
      break;
      case 2:
        whiteLevel = (75 * 255) / 100;
        blueLevel = 0;
      break;
      case 3:
        whiteLevel = 255;
        blueLevel = 0;
      break;
      case 4:
        whiteLevel = 0;
        blueLevel = 255;
      break;
    }
    analogWrite(ledPinwhite, whiteLevel);
    analogWrite(ledPinblue, blueLevel);

is an almost literal translation of

  • ...off
  • White on 30% (blue off)
  • White on 75 % (blue off)
  • White on 100% (blue off)
  • blue on 100% (White off)

mashm:
sorry for my bad english...i will try again to explain my idea:
the lamp starts with both leds of (Initial state). now i press the button and the Output of the White should be 1/4 pwm:

So, maybe you need two variables, to record the current state of each of the LEDs.

ledBlueState = 0;
ledWhiteState = 0;

if (switchWasPressed) {
  if((ledBlueState == 100)  && (ledWhiteState == 100)) {
    ledBlueState = 0;
    ledWhiteState = 0;
  }
  else if((ledBlueState == 0) && (ledWhiteState == 100)) {
    ledBlueState = 100;
  } 
  else {
    ledWhiteState += 25;
  }
}

i am not a programmer

I am a diver, mainly in the English Channel where a good torch is essential. Sorry to go off topic but I am going to ask you to think carefully about your design decision. Underwater torches which go from 100% to off, when what you want to do is turn the brightness down, are extremely annoying.

On the surface, a bright torch allows you to see further but underwater, the distance is limited by the particles in the water, reducing your depth of field, which a torch does not alter. You don't need a lot of light when it is dark underwater, because your iris opens up and after a few minutes you have very good night vision. When there is not much ambient light, turning your torch up causes more light to be reflected back from the particles in the water (backscatter) and reduces your night vision - much quicker than the time it takes to recover. It sounds counter intuitive but underwater, a bright light is most useful when there is lots of ambient light around and your night vision is already limited.

A torch which goes from very bright to off, when there is little ambient light around, will leave you just about blind. I think it would be better, safer even, for your torch to go 0->25->50->100->50->25->0. To be honest, I would much prefer a separate on/off switch, well away from the power adjustment. Similarly with the low battery. Don't flash the torch as that can ruin night vision and leave you blind. Dim the torch, relative to the power it is set at.

Hi Matts,

i am also a diver. till now i have a hartenberger dive light with a halogen bulp. i am happy with this. very robust and good color rendition. but now i want also a dive light with a (deep)blue + white led for night diving. i have also a high power uv light with a nichia 365nm led, but without white leds. i also know about the night vision. my other hobby is astro photography.
i can not make an extra switch for powering of, cause the flashlite is i faulty body from ebay. it is this body:
http://www.amazon.com/Intova-SuperNova-Rechargeable-Scuba-Diving/dp/B006VEMJ3K

i think i understand your code and hope i can write some new code with it.

@Awol thanks too i will try to understand your code too!

thanks alot.

Hi,

my arduino hardware arrived yesterday so i did some teste. i have now a working sollution and read some more about switch case.

this is my sollution:

#define whiteled 11 //assign pin 11 to white led
#define blueled 10 //assign pin 10 to blue led
#define BUTTON 9 //assign pin 7 to pushbutton
#define SAMPLING 50 //50milliSecond per press, used for debouncing

static unsigned long TIMER = 0; //record current millis()
byte state = 0; //val used to check current status of pushbutton later in the program
int previous=LOW;
int reading;

void setup()
{
pinMode(whiteled,OUTPUT);
pinMode(blueled,OUTPUT);
pinMode(BUTTON,INPUT);
  }

void loop()
{ 
  reading = digitalRead(BUTTON);
  if(millis() - TIMER >= SAMPLING) //sampling ~= 50mS
  {      TIMER = millis();     if(reading == HIGH && previous == LOW) //button pressed, pulled low
  {       state++; //increment state 
          delay(500); //delay for not ramping up if pressed to long
        } 
      if(state == 1)
      { digitalWrite(blueled,0);
        analogWrite(whiteled, 64);
          }
        
      else if(state == 2)
      { analogWrite(whiteled, 128);
        digitalWrite(blueled,0);
          } 
        
      else if(state == 3)
    { analogWrite(whiteled, 255);
      digitalWrite(blueled,0);
          }
        
      else if(state == 4)
      {  analogWrite(whiteled, 0);
         digitalWrite(blueled,1);
           }
         
       else if(state > 4)
     {  state = 0;
        analogWrite(whiteled, 0);
        digitalWrite(blueled,0);
            } 
          
        } 
      
    }

and i think this will also work:

#define whiteled 11 //assign pin 11 to white led
#define blueled 10 //assign pin 10 to blue led
#define BUTTON 9 //assign pin 7 to pushbutton
#define SAMPLING 50 //50milliSecond per press, used for debouncing

static unsigned long TIMER = 0; //record current millis()
byte state = 0; //val used to check current status of pushbutton later in the program
int previous=LOW;
int reading;
int whiteLevel;
int blueLevel;

void setup()
{
pinMode(whiteled,OUTPUT);
pinMode(blueled,OUTPUT);
pinMode(BUTTON,INPUT);
  }

void loop()
{ 
  reading = digitalRead(BUTTON);
  if(millis() - TIMER >= SAMPLING) //sampling ~= 50mS
  {      TIMER = millis();     if(reading == HIGH && previous == LOW)
  {       state++; //increment state 
          delay(500); //delay for not ramping up if pressed to long
        }
        
 switch (state)
    {
      case 0:
        whiteLevel = 0;
        blueLevel = 0;
      break;
   
      case 1:
        whiteLevel = (30 * 255) / 100;
        blueLevel = 0;
      break;
   
      case 2:
        whiteLevel = (75 * 255) / 100;
        blueLevel = 0;
      break;
   
      case 3:
        whiteLevel = 255;
        blueLevel = 0;
      break;
   
      case 4:
        whiteLevel = 0;
        blueLevel = 255;
      break;
      
      default:
        state = 0;
      
    }
    analogWrite(whiteled, whiteLevel);
    analogWrite(blueled, blueLevel);
         
         
          
        } 
      
    }

now i would like to add some battery monitor that ramps down the light if it will go empty.

markus

What is this crap?

  {      TIMER = millis();     if(reading == HIGH && previous == LOW) //button pressed, pulled low

Get your enter key fixed or bang it more often.