# mPy - LDR exercise. Demonstrates exceptions on samples.
# copyright by Anthony Vogelaar, Perth Scotland
# rev 0.10  2025-04-23  initial release

# https://docs.micropython.org/en/latest/esp32/quickref.html

import	time
from	machine		import	Pin, ADC

# ==================== hardware =========================

ldr    = ADC(35, atten=ADC.ATTN_11DB)		# 0.15 .. 2.45V
btn000 = Pin(14, Pin.IN, Pin.PULL_UP)		# red    button calibrate   0%
btn100 = Pin(27, Pin.IN, Pin.PULL_UP)		# yellow button calibrate 100%
btnSmp = Pin(26, Pin.IN, Pin.PULL_UP)		# green button  sample

# ====================== Button =========================

# debounce button class
class Button:
    
    def __init__(self, btn):				# btn is instance of Pin
        self.btn   = btn
        self.count = 0						# debounce counter
        
        
    # call repeatedly ex @ 50 mSec
    def exe(self):
        if self.btn():						# if not pressed
            self.count = 0					
        elif self.count < 3:				# else pressed
            self.count += 1
            if self.count == 3: return True	# three consecutive samples low
                                            # else return None
            
# ====================== Main ===========================

class ELdrHigh(Exception): pass				# user exceptions
class ELdrLow (Exception): pass

class Main:
    
    def __init__(self):
        self.btn_000   = Button(btn000)				# Button Red      0%
        self.btn_100   = Button(btn100)				# Button Yellow 100%
        self.btnSamp   = Button(btnSmp)				# Button Green  Sample
        self.level_000 = 0
        self.level_100 = 4095
        while True:
            try            : self.exe()
            except ELdrHigh: print('\n---> ELdrHigh exception')
            except ELdrLow : print('\n---> ELdrLow exception')
#            except Exception as exc:				# alternative way of exception processing
#                print('\n', type(exc), exc)
            time.sleep_ms(50)						# loop period


    # called @ 20 Hz
    def exe(self):
        y1 = ldr.read()								# light intensity 0..4095
        y2 = int(100 * (y1 - self.level_000) / (self.level_100 - self.level_000))	# normalised 0..100
        if self.btn_000.exe(): self.level_000 = y1	# calibrate   0% at button red    press
        if self.btn_100.exe(): self.level_100 = y1	# calibrate 100% at button yellow press
        print(f'{y2:4}', end='')					# compact shell presentation
#        print(y2)									# for use with plotter
        if self.btnSamp.exe():						# sample if button green pressed
            if   y2 > 80: raise ELdrHigh('LDR > 80%')
            elif y2 < 20: raise ELdrLow ('LDR < 20%')
        
        
Main()

# ======================= end ===========================
