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.
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”).
;===========================================| ;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