Adapting Assembler code to Arduino

Hi guys,

I’m working on building a lightning trigger that triggers a camera whenever a light sensor sees a lightning strike. I found some code online that unfortunately is written in Assembler but I’d like to understand what its doing and basically recreate it using an Arduino. Unfortunately, Assembler is completely foreign to me. :frowning:

From what I understand the micro gets it’s input on lines 17 and also 18. Line 18 is the signal straight from the light sensor while the signal to pin 17 comes from a high pass filter that only triggers on fast light changes. When the PIC sees a ‘flash’ it triggers the camera through pin 9.

Here is the assembler code:

	LIST	p=16F628		
	include "P16F628.inc"		
	ERRORLEVEL	0,	-302	
	__config 0x3F18			


		cblock	0x20			;start of general purpose registers
            Cz1,Cz2,Cz3
			hold			;Comparator pervious state	
  		    count			;used in looping routines
			count1			;used in delay routine
			counta			;used in delay routine
			countb			;used in delay routine
			tmp1			;temporary storage
			tmp2
			templcd			;temp store for 4 bit mode
			templcd2

			Value				; Value to be sent to LEDs
			Dirty				; Is LCD display dirty?
			Digit0				; First digit for display
			Digit1				; Second digit for display		
			Digit2				; Third digit for display
			DigitIndex			; Digit pointer
			J					; 101us delay outer loop counter
			K					; 101us delay inner loop counter
			L					; 4.1ms delay outer loop counter
			M					; 4.1ms delay inner loop counter

		endc

LCD_PORT	Equ	PORTB
LCD_TRIS	Equ	TRISB
LCD_RS		Equ	0x00			;LCD handshake lines RS PORTB RB0
LCD_RW		Equ	0x01			;RW PORTB RB1
LCD_E		Equ	0x02			;E PORTB RB2


C1OUTMASK   	Equ b'01000000'		;Comparator1 output bit
C2OUTMASK	        Equ b'10000000'		;Comparator2 output bit

SW1		Equ 7				;RB7 (pin 13)
TRIGGER     	Equ 3				;RB3
METERING    	Equ 2				;RB2
LED_CAL		Equ 5				;RB5
LED_MODE	Equ 4				;RB4
		org	0x0000

;Chip funkciok inicializaslasa

      		clrf PORTA
      		clrf PORTB

		movlw 0x32       ;Internal voltage reference mode CM<2:0>=010
	 	movwf	CMCON


SetPorts	
        	bsf 	STATUS,	RP0	;select bank 1
		movlw	b'10000000'	;RB7 input RB6-0 input
		movwf	PORTB		;PORTB - Mind a 8 vezetek        
		movlw   0x07				
        	movwf   TRISA		; RA<2:0> Input RS<4:3> output

		bcf 	STATUS,	RP0	;select bank 0



;startup
calibrate1

;time to settle down
				bsf  PORTB, LED_MODE
				bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
                call Delay50ms
				bsf  PORTB, LED_MODE
				bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
                call Delay50ms
				bsf  PORTB, LED_MODE
				bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
                call Delay50ms
				bsf  PORTB, LED_MODE
				bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
                call Delay50ms
				bsf  PORTB, LED_MODE
				bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
                call Delay50ms
				bsf  PORTB, LED_MODE
				bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
                call Delay50ms
   


calibrate			call vrset1041V
				bcf  PORTB, LED_MODE		;Mode led 0
		

comploop0			bcf   PORTB, LED_CAL
				bsf   PORTB, LED_MODE
comploop1		
				btfss PORTB, SW1
				goto mode_select_switch
				
				movf CMCON,w
				andlw C2OUTMASK			;1 az output bit ?
				btfsc STATUS,Z		
		        	goto comploop0
				
				bsf PORTB,LED_CAL
                		bcf PORTB,LED_MODE
				goto comploop1


mode_select_switch
				Call Delay250ms
			
				Call vrset0625V

				bsf PORTB, LED_MODE		;mode led on
				bcf PORTB, LED_CAL		;calibrate led off
				Call Delay250ms
				bsf PORTB, LED_MODE		;mode led on
				bcf PORTB, LED_CAL		;calibrate led off
				bcf PORTB, TRIGGER
				bsf PORTB, METERING


 
Triggerloop 	btfss PORTB, SW1
				goto exit_trigger_mode

				movf CMCON,w
				andlw C1OUTMASK			;1 az output bit ?
				btfsc STATUS,Z		
		        	goto Triggerloop

       ;Trigger !!

				bsf PORTB, TRIGGER
				call Delay250ms
				call Delay250ms
				bcf  PORTB, TRIGGER
				call Delay50ms
				bcf  PORTB, METERING
				; villog
				
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
				call Delay250ms
				bsf  PORTB, LED_MODE
                		bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
				call Delay250ms
				bsf  PORTB, LED_MODE
                		bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
				call Delay250ms
				bsf  PORTB, LED_MODE
		                bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
				call Delay250ms
				bsf  PORTB, LED_MODE
                		bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
				call Delay250ms
				bsf  PORTB, LED_MODE
                		bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
				call Delay250ms
				bsf  PORTB, LED_MODE
                		bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
				call Delay250ms
				bsf  PORTB, LED_MODE
                		bcf  PORTB, LED_CAL
				call Delay250ms
				bcf  PORTB, LED_MODE
				bsf  PORTB, LED_CAL
				call Delay250ms
				bsf  PORTB, LED_MODE
                		bcf  PORTB, LED_CAL
				bsf  PORTB, METERING
				
		        	goto Triggerloop

exit_trigger_mode

				Call Delay250ms
				bcf PORTB,LED_MODE
				bcf PORTB,METERING
				goto calibrate1



;Set VREF to 1.041V
vrset1041V
		bsf 	STATUS, RP0			;select bank1
		movlw	0xE5				;1.041V (for check gain)
		movwf	VRCON
		bcf		STATUS,	RP0
        	call	Delay250ms			;Time to settle down VREF
		return
    
;Set VREF to 0.625V
vrset0625V
		bsf 	STATUS, RP0			;select bank1
		movlw	0xE3				;0.625V (for check gain)
		movwf	VRCON
		bcf		STATUS,	RP0
        	call	Delay250ms			;Time to settle down VREF
		return









Delay250ms			movlw	d'250'			;delay 250 ms (4 MHz clock)
				movwf	count1
d1A				movlw	0xC7
				movwf	counta
				movlw	0x01
				movwf	countb
Delay_0A
				decfsz	counta, f
				goto	$+2
				decfsz	countb, f
				goto	Delay_0A

				decfsz	count1	,f
				goto	d1A
				retlw	0x00


Delay50ms		movlw	d'100'			;delay 50 ms (4 MHz clock)
				movwf	count1
d1B				movlw	0xC7
				movwf	counta
				movlw	0x01
				movwf	countb
Delay_0B
				decfsz	counta, f
				goto	$+2
				decfsz	countb, f
				goto	Delay_0B

				decfsz	count1	,f
				goto	d1B
				retlw	0x00
		end

My questions are:

  • What is going on in the ‘calibrate’ function?
  • How does the micro detect a lightning flash? Is it using the input on line 17? Or line 18? Is it comparing 17 to 18? Something else?

If anyone could help me make any sense of the assembler code I would be very grateful! I'm also including the circuit schematic so you can get a better idea of what going on.

Have you downloaded and studied the P16F628 data sheet so you have some idea of how the device works?

Quite honestly you are better off writing your code in C on an Arduino. All machine code is specific to the processor it runs on, so it is not easy converting from one to the other because there is no one to one conversion.

By the way your schematic has the LEDs wired up the wrong way round, they will never light up like that.

I'll admit that I only looked at it. It's a 178 pages and a bit overwhelming for me.

I was mainly after understanding what it does so that I can replicate the function with an Arduino and there where I was struggling.

Good catch on the LED's! This isn't my schematic but I didn't even notice it.

Where did you find this project? If no explanation of the functions is offered, look for a better project tutorial.

AMS makes a lighting detector chip. Take a look a the Sparkfun module and tutorial.

BTW the code uses the analog comparators of the PIC processor, so it is just looking for a very rapid increase in the light level (via the high pass filter, relative to background). Easy to do on any microprocessor.

Looks like it is RF-based; might be able to make it more directional to match the camera field of view.

The AS3935 is capable of detecting lightning up to 40km away with an accuracy of 1km to the storm front with a sensitive antenna tuned to pick up lightning events in the 500kHz band.

You may wish to search in the "Arduino" area:

https://www.google.com/search?q=Arduino+lightning+detector+for+camera

In the film photography space, we used to set a time exposure and pray we would get lucky.
Lightning Photography - advice from award winning Photographer | Royal Meteorological Society (rmets.org)

That is a pretty interesting idea! The Sparkfun board has a 500 kHz antenna module built in (Coilcraft MA5532-AE) but I imagine that a loopstick antenna would work fine, and be reasonably directional.

On the other hand, an optical detector in a black tube would be even more directional.

Until I really searched, I had no idea that some digital cameras have a lightning profile best practice... less guess.

The Best Full-Frame Cameras for 2022 | PCMag

We also have some tips for enthusiasts who want to get more out of their camera, and guides with instructions on getting great shots of fireworks and lightning.

Nice article at How to Photograph Lightning | PCMag

I'll take a WAG.
With the switch in the Cal mode, ou adjust that pot on the OPT101 until its output just balances a selected comparator reference of 0.625V or 1.041V. The Cal and Mode LEDs bounce back and forth until that happens. It starts off at the higher voltage and moves to the lower to fine tune.

When you move the switch to the trigger mode it enables the metering optocoupler which must put the camera in the metering mode and then when a lightning flash is detected the shutter is opened through the other optocoupler.

When lightning trips it you get an arcade like light show from the flashing LEDs.

Some other existing projects

https://create.arduino.cc/projecthub/mircemk/sensitive-arduino-lightning-detector-with-homemade-sensor-7afaa5

There are tons

When a lightning strikes, a huge amount of energy is released in different forms. The most obvious are light and sound, the latter being a by-product of the rate of temperature increase of the immediate particles surrounding the lightning bolt, which then causes the sound. But, that is not all. Lightnings emit large amount of electromagnetic radiation in the VLF (Very Low Frequency) and LF (Low Frequency) range, typically ranging from 3kHz to 300kHz. VLF and LF are similar to light waves, your WiFi waves and also your microwave oven waves, but with the difference of operating at lower frequencies. eg. WiFi normally operates at around 2.4GHz, that’s 2.4 billion oscillations per second. VLF and LF operates at lower frequencies, and with an Arduino we can capture frequencies around 7kHz. The advantages in using this kind of radiation for lightning detection is that normally nothing gives out large bursts as seen in lightnings, around this frequency; and being an electromagnetic wave it travels at the speed of light, which means the sensor will detect lightnings as they happen (a few micro seconds after). Our little Arduino will have an antenna (sort of), a piece of wire that will pick fluctuations in electromagnetic spectrum specifically around the 7-9kHz. These fluctuations will induce a small voltage +ve or -ve in the wire. We can pick these fluctuations using Arduino’s analog pins.

Another solution is to teach AI what lightning looks like and let it watch horizon

Your image acquisition and ML model would need to run pretty fast or it will tell you I’ve seen a lightning but it’s gone now :slight_smile:

but you run recognition on captured data so you just save what you saw

Right you have the image you can keep if it’s original quality, I thought you were suggesting to analyze a low res picture to decide on triggering the high quality camera.

Frame rate will be your limiting factor if you need to process 20+ megs of data for a good quality shot

This project from 2011 has likely been derived directly from the one in the OP: Zeus: trigger your camera with lightning – Viktor’s DIY Blog except he has used optocouplers instead of relays. There is a description in the text of how it is calibrated. The code is (still?) available on request.

I actually found this project from a discussion somewhere online but I don't remember where. There was a link to a Hungarian website that no longer existed but I managed to find it using the wayback machine.
That Spaprkfun detector looks interesting but I'm afraid that it won't be fast enough to detect the lightning and trigger the camera before its gone.

Do you know what signal the code I posted compares? The filtered or the unfiltered? And why are there the 2 signals. And does it compare it/them to an internal reference?

You're right, that does look very similar. I read the description but I still don't really understand what exactly the code is doing...