AG:MF01

AGMF01_00

AG:MF01-2009/WTMC Flashlight

The AGMF series flashlights are like the AGXF and AGUF series in basic structure, and like the AGXF in the use of a microcontroller, but differ in that the AGMF aims to be both smaller and metallic (the “M” stands for miniature, or micro, or metal, or microcontroller, or…).  The AGMF Flashlight is probably one of my most professional I’ve ever built, for several reasons. The most obvious is that it has a polished aluminum case and lens. But besides that, there are some more subtle ways it has a higher level of professionalism. One way is that it allows for replacing the Li-Ion cell, like a normal flashlight. Additionally, it has a microcontroller which allows for both remote control and advanced LED controls.


Design

Like I did with the previous AG:XF01 Flashlight, in making the AG:MF01 flashlight, my design phase started with drawings and sketches of the shape and functions of the planned flashlight. I actually created an initial design on Google SketchUp, although this would turn out to be quite different from my final design.

AG:MF01 Design

AG:MF01 Design

I also created a list of functions I planned to employ:

  • pic10f222 microcontroller
  • Most lights powered by microcontroller
  • Li-Ion cell
  • Cree R2 XP-E LED
  • Constant on backlights for Main switch
  • Main switch has backlight
  • Main mode of operation: Light output when main switch on
  • Secondary mode: IR input
  • IR controlled: W
  • PTC shortcircuit protection switch
  • Thermometer to measure White LED (including IR control):
    • auto LED lower power when >45C and beep warning (3.6v)
    • LED shutoff when >55C and beep warning (3.6v)
  • USB battery charge or external wall mount charge
  • Latching main switch
  • Keyring
  • WDT enabled to ensure continued running of MCU
  • Aluminum case & glued parts ensure ruggedness
  • Up to <250 Lumens of light output

From the list of functions I intended to employ, you can see that this was supposed to be a fairly advanced flashlight. In a way, it would be more advanced than my AGXF flashlight, but also, it would be simpler. As I mentioned, the flashlight would have am IR receiver for remote control purposes. (This IR Receiver would follow the same protocol described in my AGXF Flashlight Project). Also like the AGXF Project, it would include a thermister for LED temperature management.

However, one of the more advanced features on this flashlight was the exponential light output function. So what I noticed with the AGXF flashlight was that varying the potentiometer key linearly produced a light output that did not seem to vary linearly. I realized the eye interprets light on a roughly logarithmic scale (I_{\text{eye}} = \log{k I_{\text{real}}}, where k is a constant associated with the potentiometer). To make the eye see a linear change in light intensity for a linear change in input voltage, I had to modify the program to change the LED’s brightness exponentially from 0.01\% to 100\%, (I_{\text{eye}} = \log{(I_{\text{real}})^k} = k \log{I_{\text{real}}}). This turned out to be fairly difficult and involved a lot of math to approximate (since there was no MCU instruction “exp”).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
;===========================================|
;ToExponent Changes the current value in    |
;A1/MSWVALH to a 2-byte C1H and C1L         |
;Takes input byte A1L                       |
;Outputs ~~ A1^(x/17) in 2-bytes: C1H, C1L  |
;===========================================|
 
ToExponent
            MOVF    A1,0        ;move contents of A1                        }approx.
            MOVWF   Temp        ;into temporary folder                      |divide
            MOVWF   MSWVALH     ;and secondary temp folder                  |by 17
            CLRF    C1H         ;and C1H = 0                                |
            SWAPF   A1,1        ;swap lower and higher nibbles              |
            MOVF    A1,0        ;then move to W                             |
            ANDLW   h'F0'       ;and get only upper nibble                  |
            MOVWF   B1          ;for B1                                     |
            MOVLW   h'0F'       ;then AND the swapped A1 with 0F            |
            ANDWF   A1,1        ;to get lower nibble only for A1            |
            COMF    B1,0        ;check if                                   |
            MOVWF   Temp        ;B1 < Temp                                  |
            MOVF    MSWVALH,0   ;by adding Temp                             |
            ADDWF   Temp,1      ;to compliment B                            |
            BTFSC   STATUS,0    ;and checking for carry                     |
            DECF    A1,1        ;decrement A1 by 1 if yes                   |
            MOVF    MSWVALH,0   ;subtract A1 from                           |
            SUBWF   B1,1        ;B1 then                                    |
            MOVLW   h'0E'       ;then add 14                                |
            ADDWF   B1,1        ;to B1                                      }
            MOVLW   h'01'       ;make C1L                                   }take
            MOVWF   C1L         ;=1                                         |exponent
ExponentPt                      ;actual exponentiation part                 |
            MOVF    A1,1        ;test if A1 = 0                             |
            BTFSC   STATUS,2    ;if yes                                     |
            GOTO    EndExp      ;end take exponent                          |
            DECF    A1,1        ;else, decrement A1 and repeat              |
            RLF     C1H,1       ;multiply C1H by 2                          |
            BCF     C1H,0       ;make sure bottom bit starts cleared        |
            RLF     C1L,1       ;multiply C1L by 2                          |
            BTFSC   STATUS,0    ;check for carry                            |
            BSF     C1H,0       ;if yes, set bit 0 of C1H                   |
            BTFSC   B1,7        ;test if highest bit B1 is 1                |
            BSF     C1L,0       ;if yes, set bit 0 of C1L                   |
            RLF     B1,1        ;multiply by 2, disregarding bit 7          |
            BSF     B1,0        ;and make sure last bit set                 |
            GOTO    ExponentPt  ;repeat if A1 != 0                          }
 
EndExp                          ;done with ToExponent
            MOVLW   h'0A'       ;set # of times to repeat
            MOVWF   CNTled      ;to 10
            BCF     STATUS,0    ;clear carry
            RLF     C1H,1       ;multiply by 2
            BTFSC   C1L,7       ;test if highest bit of C1L set
            BSF     C1H,0       ;if yes, set LSB of C1H
            RLF     C1L,1       ;then multiply C1L by 2
            Call    Whitemsw    ;WLED output
            GOTO    Whitemode   ;repeat

Here, you can see the code I used, which approximates the following function: (A1)^{\frac{x}{17}}.

And here’s the final code I ran on the MCU: OS.asm