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.


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

;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	|

			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