class UltraSonicMeter(object): def __init__(self): self.tmp = self.time = 0 self.cnt = 0 self.fr = 0 self.trig = Pin('X12', Pin.OUT_PP, Pin.PULL_NONE) echoR = Pin('X1', Pin.IN, Pin.PULL_NONE) echoF = Pin('X2', Pin.IN, Pin.PULL_NONE) self.micros = pyb.Timer(5, prescaler=83, period=0x3fffffff) self.timer = Timer(2, freq=1000) self.timer.period(3600) self.timer.prescaler(1375) self.timer.callback(lambda e: self.run_trig()) extR = ExtInt(echoR, ExtInt.IRQ_RISING, Pin.PULL_NONE, self.start_count) extF = ExtInt(echoF, ExtInt.IRQ_FALLING, Pin.PULL_NONE, self.read_dist) def run_trig(self): self.trig.high() pyb.udelay(1) self.trig.low() def start_count(self, line): self.micros.counter(0) self.time = self.micros.counter() self.timer.counter(0) def read_dist(self, line): end = self.micros.counter() micros = end-self.time distP1 = micros//5 distP2 = micros//6 distP3 = (distP1-distP2)//10*2 dist = distP2+distP3 if dist != 0: self.cnt += 1 self.fr += dist if self.cnt == 15: tmp = self.tmp dist = self.fr//self.cnt if tmp != dist: print(dist, 'mm') self.tmp = dist self.cnt = 0 self.fr = 0
class encoder(): # Period value is inclusive. counter will have max value == period # Only use channel 1 a and 2 of timer, and never 1N and 2N def __init__(self, pin_number_a, pin_number_b, period, timer_number): # Timer registers, needed for direction regs = [ 0, stm.TIM1, stm.TIM2, stm.TIM3, stm.TIM4, stm.TIM5, stm.TIM6, stm.TIM7, stm.TIM8, stm.TIM9, stm.TIM10, stm.TIM11, stm.TIM12 ] self.direction_register = regs[timer_number] + stm.TIM_CR1 # Pins pin_a = Pin(pin_number_a, Pin.IN) # PE9 pin_b = Pin(pin_number_b, Pin.IN) # PE11 # Encoder self.encoder = Timer(timer_number, prescaler=0, period=period) self.encoder.channel(1, Timer.ENC_AB, pin=pin_a) self.encoder.channel(2, Timer.ENC_AB, pin=pin_b) self.period = period self.rollover = 0 self.encoder.callback(self.loop_counter_rollover) def loop_counter_rollover(self, timer): if self.get_direction() == 0: self.rollover = self.rollover + 1 else: self.rollover = self.rollover - 1 def get_degrees(self): return 360.0 * self.encoder.counter( ) / self.period # encoder period is inclusive def get_degrees_total(self): return self.rollover * 360.0 + self.get_degrees() def get_direction(self): return (stm.mem32[self.direction_register] & 0x10) >> 4
def pulseIn(pin, st): start = 0 end = 0 mas_filtr = [] micros = Timer(5, prescaler=83, period=0x3fffffff) micros.counter(0) if st: while pin.value() == 0: start = micros.counter() while pin.value() == 1: end = micros.counter() else: while pin.value() == 1: start = micros.counter() while pin.value() == 0: end = micros.counter() micros.deinit() res = (end - start) mas_filtr = [res for i in range(10)] return filtr_mas(mas_filtr)
n = 0 timer = Timer(2) logger = logging.getLogger(__name__) logger.info("Latency test RS232") logger.info("Initializing interface.") interface = rs232_tmcl_interface(data_rate=DATA_RATE) logger.info("Performing test.") ticks = (WORST_CASE_LATENCY * PAYLOAD * pyb.freq()[2] * 2) / 1000 prescaler = int(ticks / 0x3fffffff) period = int((WORST_CASE_LATENCY * PAYLOAD * pyb.freq()[2] * 2) / (1000 * (prescaler + 1))) while (n < N_SAMPLES): timer.counter(0) timer.init(prescaler=prescaler, period=period, callback=timeout) for i in range(0, PAYLOAD): interface.send_request_only(TMCL_Request(MODULE_ID, 1, 2, 3, 4, 5), host_id=HOST_ID, module_id=MODULE_ID) try: for i in range(0, PAYLOAD): interface.receive_reply(module_id=MODULE_ID, host_id=HOST_ID) except: pass timer.deinit() if (not (tout)): counter = timer.counter() logger.debug("Measured delta ticks: {}".format(counter)) # update values
class motor_with_encoder(): def __init__(self, motor, encoder, loop_timer_number): # loop_timer_number TIMn self.motor = motor self.encoder = encoder self.state_org = state_organizer() self.init_loop_timer(loop_timer_number) # Set an unused timer number, the values are based on a timer freq of 108MHz def init_loop_timer(self, timer_number): self.rollover = 0 self.loop_timer_period = 0xffff self.loop_timer = Timer( timer_number, prescaler=10800, period=self.loop_timer_period) # timer fq = 10000Hz 1s = 10000 self.loop_timer.callback(self.loop_counter_rollover) def loop_counter_rollover(self, timer): self.rollover = self.rollover + 1 # loop timer in milli seconds def get_loop_timer_ms(self): ctr = self.loop_timer.counter( ) + self.rollover * self.loop_timer_period return ctr / 10 # loop timer in seconds def get_loop_timer_s(self): ctr = self.loop_timer.counter( ) + self.rollover * self.loop_timer_period return ctr / 10000 def reset_loop_timer(self): self.rollover = 0 self.loop_timer.counter(0) def get_deg_error(self, deg_set, deg): err = deg_set - deg if err < -180: # 0 - 300 = -300 -> 60 err = err + 360 elif err > 180: # 270 - 30 = 240 -> -120 err = err - 360 return err def set_position(self, deg_set, k_p, k_i, acceptable_error=0.05): # timer = Timer(12, prescaler=10800, period=0xffff) #timer fq = 10000Hz 1s = 10000 _I = 0 # I@t-1 a = 0 err_prev = 999 _t = self.get_loop_timer_s() while True: a = a + 1 if a > 1000: print('Error: ', err, 'Power: ', power, 'K: ', K, 'I: ', I, 'Degrees: ', self.encoder.get_degrees()) a = 0 # asyncio.sleep(0.001) #Loop time is 1ms time.sleep_us(1000) t = self.get_loop_timer_s() dt = t - _t self.reset_loop_timer() deg = self.encoder.get_degrees() err = self.get_deg_error(deg_set, deg) if abs(err) < acceptable_error: err = 0 if err == err_prev: print('Final Error: ', err, 'Power: ', power, 'K: ', K, 'I: ', I, 'Degrees: ', self.encoder.get_degrees()) return err_prev = err I = dt * err + _I # Integrator # Cap integrator if I > 5: I = 5 elif I < -5: I = -5 _I = I K = err # Proportional power = k_p * K + k_i * I self.motor.set_power(power) _t = t # returns the average velocity since the last call def get_angular_velocity(self): # try this: https://docs.micropython.org/en/v1.9.3/pyboard/reference/speed_python.html#caching-object-references vel = self.state_org.vel # requires fewer object lookups time = self.get_loop_timer_s() position = self.encoder.get_degrees_total() dPosition = position - vel._pos dt = time - vel._time vel._pos = position vel._time = time return dPosition / dt def set_velocity(self, vel_set, k_p, k_i, loop_time_us=1000, filter_val=1): _v = self.get_angular_velocity() a = 0 _t = self.get_loop_timer_s() _I = 0 _vel = 0 while True: a = a + 1 if a > 200: print('v filter: ', v, 'Velocity: ', vel_act, 'Error: ', err, 'Power: ', power, 'K: ', K, 'I: ', I, '\n') a = 0 time.sleep_us(loop_time_us) t = self.get_loop_timer_s() dt = t - _t vel_act = self.get_angular_velocity() v = vel_act * filter_val + _v * (1 - filter_val) err = vel_set - v I = dt * err + _I # Integral K = err # Proportional power = k_p * K + k_i * I self.motor.set_power(power) _t = t _I = I _v = v
class sr04distance(object): """Driver for SR05 sonic distance sensor. """ # _MAXINCHES = const(20) #maximum range of SR04. def __init__( self, tpin, epin, timer = 2 ) : '''tpin = Timer pin. epin = Echo pin. timer = Timer #. ''' if type(tpin) == str: self._tpin = Pin(tpin, Pin.OUT_PP, Pin.PULL_NONE) elif type(tpin) == Pin: self._tpin = tpin else: raise Exception("trigger pin must be pin name or pyb.Pin configured for output.") self._tpin.low() if type(epin) == str: self._epin = Pin(epin, Pin.IN, Pin.PULL_NONE) elif type(epin) == Pin: self._epin = epin else: raise Exception("echo pin must be pin name or pyb.Pin configured for input.") # Create a microseconds counter. self._micros = Timer(timer, prescaler = 83, period = 0x3fffffff) def __del__( self ) : self._micros.deinit() @property def counter( self ) : return self._micros.counter() @counter.setter def counter( self, value ) : self._micros.counter(value) @property def centimeters( self ) : '''Get # of centimeters distance sensor is reporting.''' start = 0 end = 0 self.counter = 0 #Send 10us pulse. self._tpin.high() udelay(10) self._tpin.low() while not self._epin.value(): start = self.counter j = 0 # Wait 'till the pulse is gone. while self._epin.value() and j < 1000: j += 1 end = self.counter # Calc the duration of the recieved pulse, divide the result by # 2 (round-trip) and divide it by 29 (the speed of sound is # 340 m/s and that is 29 us/cm). return (end - start) / 58.0 @property def inches( self ) : #Get distance in inches. return self.centimeters * 0.3937
class SR04Distance(object): """ """ maxinches = 20 #maximum range of SR04. def __init__( self, tpin, epin, timer=2 ) : """ """ if type(tpin) == str: self._tpin = Pin(tpin, Pin.OUT_PP, Pin.PULL_NONE) elif type(tpin) == Pin: self._tpin = tpin else: raise Exception("trigger pin must be pin name or pyb.Pin configured for output.") self._tpin.low() if type(epin) == str: self._epin = Pin(epin, Pin.IN, Pin.PULL_NONE) elif type(epin) == Pin: self._epin = epin else: raise Exception("echo pin must be pin name or pyb.Pin configured for input.") # Create a microseconds counter. self._micros = Timer(timer, prescaler=83, period=0x3fffffff) def __del__( self ) : self._micros.deinit() @property def counter( self ) : return self._micros.counter() @counter.setter def counter( self, value ) : self._micros.counter(value) @property def centimeters( self ) : start = 0 end = 0 self.counter = 0 #Send 10us pulse. self._tpin.high() udelay(10) self._tpin.low() while not self._epin.value(): start = self.counter j = 0 # Wait 'till the pulse is gone. while self._epin.value() and j < 1000: j += 1 end = self.counter # Calc the duration of the recieved pulse, divide the result by # 2 (round-trip) and divide it by 29 (the speed of sound is # 340 m/s and that is 29 us/cm). return (end - start) / 58 @property def inches( self ) : return self.centimeters * 0.3937
spi = SPI(1, SPI.MASTER, baudrate=30000, polarity=0, phase=0, bits=8) x5 = Pin('X5', Pin.OUT_PP) tim = Timer(4, freq=1) bits = (0, 1, 2, 4, 8, 16, 32, 64, 128) reg1, reg2 = 0, 0 imgLOVE = (22, 23, 26, 27, 31, 34, 35, 38, 41, 48, 52, 57, 63, 66, 74, 75) img0 = (24, 25, 33, 36, 43, 46, 53, 56, 63, 66, 74, 75) img1 = (25, 34, 35, 45, 55, 65, 75) img2 = (24, 25, 33, 36, 46, 55, 64, 73, 74, 75, 76) img3 = (24, 25, 33, 36, 45, 56, 63, 66, 74, 75) img4 = (23, 26, 33, 36, 43, 44, 45, 46, 56, 66, 76) img5 = (23, 24, 25, 26, 33, 44, 45, 56, 63, 66, 74, 75) img6 = (25, 34, 43, 44, 45, 53, 56, 63, 66, 74, 75) img7 = (23, 24, 25, 26, 36, 45, 55, 65, 75) img8 = (24, 25, 33, 36, 44, 45, 53, 56, 63, 66, 74, 75) img9 = (24, 25, 33, 36, 44, 45, 46, 56, 65, 74) animation = (img9, img8, img7, img6, img5, img4, img3, img2, img1, img0, imgLOVE) for ani in animation: while tim.counter() < 18000: if ani == imgLOVE: tim.counter(0) for i in ani: reg1 = bits[-(i // 10)] reg2 = bits[(i % 10)] update(~reg1, reg2) tim.counter(0)
class Motor(object): def __init__(self, freq, encoder_period, motor): if motor == 1: # Configure driver pins pin = Pin(Pins.MOTOR1_PWM, Pin.OUT) timer_pwm = Timer(Timers.MOTOR1_PWM, freq=freq) self.pwm_pin = timer_pwm.channel(Timers.MOTOR1_PWM_CHANNEL, Timer.PWM, pin=pin) self.direction_pin = Pin(Pins.MOTOR1_DIRECTION, Pin.OUT) # Configure encoder pins pin_a = Pin(Pins.MOTOR1_ENC_A, Pin.AF_PP) pin_b = Pin(Pins.MOTOR1_ENC_B, Pin.AF_PP) self.timer_enc = Timer(Timers.MOTOR1_ENC, prescaler=0, period=encoder_period) self.timer_enc.channel(Timers.MOTOR1_ENC_A_CHANNEL, Timer.ENC_AB, pin=pin_a) self.timer_enc.channel(Timers.MOTOR1_ENC_B_CHANNEL, Timer.ENC_AB, pin=pin_b) elif motor == 2: # Configure driver pins pin = Pin(Pins.MOTOR2_PWM, Pin.OUT) timer_pwm = Timer(Timers.MOTOR2_PWM, freq=freq) self.pwm_pin = timer_pwm.channel(Timers.MOTOR2_PWM_CHANNEL, Timer.PWM, pin=pin) self.direction_pin = Pin(Pins.MOTOR2_DIRECTION, Pin.OUT) # Configure encoder pins pin_a = Pin(Pins.MOTOR2_ENC_A, Pin.AF_PP) pin_b = Pin(Pins.MOTOR2_ENC_B, Pin.AF_PP) self.timer_enc = Timer(Timers.MOTOR2_ENC, prescaler=0, period=encoder_period) self.timer_enc.channel(Timers.MOTOR2_ENC_A_CHANNEL, Timer.ENC_AB, pin=pin_a) self.timer_enc.channel(Timers.MOTOR2_ENC_B_CHANNEL, Timer.ENC_AB, pin=pin_b) elif motor == 3: # Configure driver pins pin = Pin(Pins.MOTOR3_PWM, Pin.OUT) timer_pwm = Timer(Timers.MOTOR3_PWM, freq=freq) self.pwm_pin = timer_pwm.channel(Timers.MOTOR3_PWM_CHANNEL, Timer.PWM, pin=pin) self.direction_pin = Pin(Pins.MOTOR3_DIRECTION, Pin.OUT) # Configure encoder pins pin_a = Pin(Pins.MOTOR3_ENC_A, Pin.AF_PP) pin_b = Pin(Pins.MOTOR3_ENC_B, Pin.AF_PP) self.timer_enc = Timer(Timers.MOTOR3_ENC, prescaler=0, period=encoder_period) self.timer_enc.channel(Timers.MOTOR3_ENC_A_CHANNEL, Timer.ENC_AB, pin=pin_a) self.timer_enc.channel(Timers.MOTOR3_ENC_B_CHANNEL, Timer.ENC_AB, pin=pin_b) return def pulse_width_percent(self, percentage): # Just a wrapper function self.pwm_pin.pulse_width_percent(percentage) return def reverse(self): # Flip the value on the direction pin reverse_value = not self.direction_pin.value() self.direction_pin.value(reverse_value) return def read_encoder_count(self): return self.timer_enc.counter()
class Encoder(): """ Abstracts a quadrature encoder to give a tick count. The count is a signed integer starting at zero. It wraps the count from the attached timer to give a seamless and continuous tick count. Overflows of the internal timer counter register should be adequatly handled. If overflows or weird behaviour occurs around the overflow points, try increasing Encoder.HYSTERESIS. Note: Only works on pin pairs 'X1' & 'X2', 'X9' & 'X10', or 'Y1', 'Y2'. The timer will be automatically selected. Both Timer 2 and 5 work for 'X1' & 'X2', but Timer 5 is preferred because Timer 2 is used for LED PWM but both can be used by changing the values of Encoder.AF_MAP. """ # Constant for decoding in single line mode SINGLE_MODE = Timer.ENC_A # Constant for decoding in quad mode DUAL_MODE = Timer.ENC_AB # Maps alternate pin function descriptions to the required timer number TIMER_MAP = {'AF1_TIM2': 2, 'AF2_TIM4': 4, 'AF2_TIM5': 5, 'AF3_TIM8': 8} # Maps pin names to the alternate function to use AF_MAP = { 'X1': 'AF2_TIM5', 'X2': 'AF2_TIM5', 'X9': 'AF2_TIM4', 'X10': 'AF2_TIM4', 'Y1': 'AF3_TIM8', 'Y2': 'AF3_TIM8' } # Defines the pin pairs that must be used PIN_PAIRS = [['X1', 'X9', 'Y1'], ['X2', 'X10', 'Y2']] # Hysteresis value to overflow detection HYSTERESIS = 12 # One full rotation of encoder def __init__(self, pinA, pinB, mode=DUAL_MODE): """ Instantiate an Encoder object. Initalises the Pins, Timer and TimerChannel for use as a quadrature decoder. Registers an overflow callback to elegantly handle counter register overflows. pinA: Any valid value taken by pyb.Pin constructor pinB: Any valid value taken by pyb.Pin constructor mode: Mode to use for decoding (Encoder.SINGLE_MODE or Encoder.DUAL_MODE) raises: Any exception thrown by pyb.Pin, pyb.Timer, pyb.Timer.channel or Exception if pins are not compatible pairs """ self._chA = Pin(pinA) self._chB = Pin(pinB) self._ticks = 0 # Check pins are compatible self._checkPins(pinA, pinB) # init pins for alternate encoder function af = self.AF_MAP[self._chA.names()[1]] channel = self.TIMER_MAP[af] af = getattr(Pin, af) self._chA.init(Pin.AF_PP, pull=Pin.PULL_NONE, af=af) self._chB.init(Pin.AF_PP, pull=Pin.PULL_NONE, af=af) # init timer self._timer = Timer(channel, prescaler=0, period=100000) # init encoder mode # self._channel = self._timer.channel(1, mode) self._timer.channel(1, mode) # setup overflow callback self._timer.callback(self._overflow) # init count register to middle of count self._timer.counter(self._timer.period() // 2) self._lastRead = self._timer.counter() def _checkPins(self, pinA, pinB): """ Check that two pins can be used for a decoding and are on the same timer. """ try: if pinA in self.PIN_PAIRS[0]: if self.PIN_PAIRS[0].index(pinA) != self.PIN_PAIRS[1].index( pinB): raise Exception() elif pinA in self.PIN_PAIRS[1]: if self.PIN_PAIRS[0].index(pinB) != self.PIN_PAIRS[1].index( pinA): raise Exception() else: raise Exception() except: raise Exception(pinA + ' & ' + pinB + ' are not on the same Timer') def ticks(self, ticks=None): """ Get or set the current tick count. Ticks is a signed integer. """ if ticks is not None: # set ticks to desired value self._ticks = ticks else: # retrieve latest count and update internals count = self._timer.counter() self._ticks = self._ticks + (count - self._lastRead) self._lastRead = count return self._ticks def _overflow(self, timer): """ Timer overflow callback to gracefully handle overflow events. If weird things are occurring, try increasing the HYSTERESIS value. """ count = timer.counter() if 0 <= count <= self.HYSTERESIS: # overflow self._ticks = self._ticks + (timer.period() - self._lastRead + count) self._lastRead = count elif (timer.period() - self.HYSTERESIS) <= count <= timer.period(): # underflow self._ticks = self._ticks - (self._lastRead + timer.period() - count) self._lastRead = count else: # hysteresis not big enough #LED(1).on() # turn on inbuilt red led to show error pass
class Encoder(): """ Abstracts a quadrature encoder to give a tick count. The count is a signed integer starting at zero. It wraps the count from the attached timer to give a seamless and continuous tick count. Overflows of the internal timer counter register should be adequatly handled. If overflows or weird behaviour occurs around the overflow points, try increasing Encoder.HYSTERESIS. Note: Only works on pin pairs 'X1' & 'X2', 'X9' & 'X10', or 'Y1', 'Y2'. The timer will be automatically selected. Both Timer 2 and 5 work for 'X1' & 'X2', but Timer 5 is preferred because Timer 2 is used for LED PWM but both can be used by changing the values of Encoder.AF_MAP. """ # Constant for decoding in single line mode SINGLE_MODE = Timer.ENC_A # Constant for decoding in quad mode DUAL_MODE = Timer.ENC_AB # Maps alternate pin function descriptions to the required timer number TIMER_MAP = {'AF1_TIM2': 2, 'AF2_TIM4': 4, 'AF2_TIM5': 5, 'AF3_TIM8': 8} # Maps pin names to the alternate function to use AF_MAP = {'X1' : 'AF2_TIM5', 'X2': 'AF2_TIM5', 'X9': 'AF2_TIM4', 'X10': 'AF2_TIM4', 'Y1': 'AF3_TIM8', 'Y2': 'AF3_TIM8'} # Defines the pin pairs that must be used PIN_PAIRS = [['X1','X9','Y1'],['X2','X10','Y2']] # Hysteresis value to overflow detection HYSTERESIS = 12 # One full rotation of encoder def __init__(self, pinA, pinB, mode = DUAL_MODE): """ Instantiate an Encoder object. Initalises the Pins, Timer and TimerChannel for use as a quadrature decoder. Registers an overflow callback to elegantly handle counter register overflows. pinA: Any valid value taken by pyb.Pin constructor pinB: Any valid value taken by pyb.Pin constructor mode: Mode to use for decoding (Encoder.SINGLE_MODE or Encoder.DUAL_MODE) raises: Any exception thrown by pyb.Pin, pyb.Timer, pyb.Timer.channel or Exception if pins are not compatible pairs """ self._chA = Pin(pinA) self._chB = Pin(pinB) self._ticks = 0 # Check pins are compatible self._checkPins(pinA, pinB) # init pins for alternate encoder function af = self.AF_MAP[self._chA.names()[1]] channel = self.TIMER_MAP[af] af = getattr(Pin, af) self._chA.init(Pin.AF_PP, pull = Pin.PULL_NONE, af = af) self._chB.init(Pin.AF_PP, pull = Pin.PULL_NONE, af = af) # init timer self._timer = Timer(channel, prescaler = 0, period = 100000) # init encoder mode # self._channel = self._timer.channel(1, mode) self._timer.channel(1, mode) # setup overflow callback self._timer.callback(self._overflow) # init count register to middle of count self._timer.counter(self._timer.period()//2) self._lastRead = self._timer.counter() def _checkPins(self, pinA, pinB): """ Check that two pins can be used for a decoding and are on the same timer. """ try: if pinA in self.PIN_PAIRS[0]: if self.PIN_PAIRS[0].index(pinA) != self.PIN_PAIRS[1].index(pinB): raise Exception() elif pinA in self.PIN_PAIRS[1]: if self.PIN_PAIRS[0].index(pinB) != self.PIN_PAIRS[1].index(pinA): raise Exception() else: raise Exception() except: raise Exception(pinA + ' & ' + pinB + ' are not on the same Timer') def ticks(self, ticks = None): """ Get or set the current tick count. Ticks is a signed integer. """ if ticks is not None: # set ticks to desired value self._ticks = ticks else: # retrieve latest count and update internals count = self._timer.counter() self._ticks = self._ticks + (count - self._lastRead) self._lastRead = count return self._ticks def _overflow(self, timer): """ Timer overflow callback to gracefully handle overflow events. If weird things are occurring, try increasing the HYSTERESIS value. """ count = timer.counter() if 0 <= count <= self.HYSTERESIS: # overflow self._ticks = self._ticks + (timer.period() - self._lastRead + count) self._lastRead = count elif (timer.period() - self.HYSTERESIS) <= count <= timer.period(): # underflow self._ticks = self._ticks - (self._lastRead + timer.period() - count) self._lastRead = count else: # hysteresis not big enough #LED(1).on() # turn on inbuilt red led to show error pass
from pyb import Pin, ADC, Timer import time led = Pin('LED1', Pin.OUT) #adc_pin = Pin(Pin.cpu.C2, mode=Pin.ANALOG) #adc_pin = Pin(Pin.cpu.C3, mode=Pin.ANALOG) #adc_pin = Pin(Pin.cpu.A0, mode=Pin.ANALOG) #adc_pin = Pin(Pin.cpu.A1, mode=Pin.ANALOG) adc_pin = Pin(Pin.cpu.B0, mode=Pin.ANALOG) #on testpad #adc_pin = Pin(Pin.cpu.B1, mode=Pin.ANALOG) #on testpad adc = ADC(adc_pin) tim = Timer(6) tim.counter() # get counter value tim.freq(20) def tick(timer): # we will receive the timer object when being called if led.value()==0: led.on() else: led.off() print(adc.read()) tim.callback(tick) time.sleep(10) tim.deinit()
class tv: def __init__(self,hres=64,progressive=False,lines=None,linetime=64,buf=None): if lines == None: lines = 262 if progressive else 525 self.lines = lines if buf == None: if progressive: self.buf = bytearray(262*hres) else: self.buf = bytearray(525*hres) else: self.buf = buf self.hres = hres self.line_time = linetime self.progressive = progressive self.sync_level = 0 self.blanking_level = 56 self.black_level = 58 self.white_level = 73 self.phase = 0 self.buffer_dac = True self.reinit() def redac(self): self.dac = DAC(Pin('X5'),buffering=self.buffer_dac) self.bmv = memoryview(self.buf)[:len(self)] self.dac_tim = Timer(6, freq=int(self.hres*1000000/self.line_time)) self.dac.write_timed(self.bmv,self.dac_tim,mode=DAC.CIRCULAR) self.frame_tim = Timer(5, prescaler=self.dac_tim.prescaler(),period=self.dac_tim.period()*len(self)) self.frame_tim.counter(self.phase) def reinit(self): self.calc_porch_magic_numbers() self.init() def set_progressive(self,prog=True): self.progressive = prog self.calc_porch_magic_numbers() self.init() def __len__(self): return self.hres*self.lines def calc_porch_magic_numbers(self): br = self.hres/self.line_time w = round(4.7*br) t = int(10.9*br+0.9)#round mostly up s = round(1.5*br) self.h_blank = [s,s+w,t] self.v_blank_e = [6,12,18] self.v_blank_o = [6,12,19] hsl = round(18*br) hsh = round(58*br) self.h_safe = [hsl-t,hsh-t] self.v_safe = [32*(2-self.progressive),208*(2-self.progressive)] def init(self): self.carrier = Pin('X1') self.tim = Timer(2, prescaler=1,period=1) self.ch = self.tim.channel(1, Timer.PWM, pin=self.carrier) self.ch.pulse_width(1) self.redac() self.be = self.bmv if not self.progressive: self.bo = self.be[len(self)//2:] self.fb = framebuf.FrameBuffer(self.buf,self.hres,self.lines,framebuf.GS8) self.fbe_mv = self.be[self.hres*21+self.h_blank[2]:] if not self.progressive: self.fbo_mv = self.bo[self.hres*43//2+self.h_blank[2]:] h = self.y_dim()//(2-self.progressive) self.fbe = framebuf.FrameBuffer(self.fbe_mv,self.hres-self.h_blank[2],h,framebuf.GS8,self.hres) if not self.progressive: self.fbo = framebuf.FrameBuffer(self.fbo_mv,self.hres-self.h_blank[2],h,framebuf.GS8,self.hres) self.clear() def set_pixel(self,x,y,v): if self.progressive: self.fbe.pixel(x,y,int(v*(self.white_level-self.black_level)+self.black_level)) else: [self.fbe,self.fbo][y&1].pixel(x,y//2,int(v*(self.white_level-self.black_level)+self.black_level)) def get_pixel(self,x,y): if self.progressive: return (self.fbe_mv[x+y*self.hres]-self.black_level)/(self.white_level-self.black_level) else: return ([self.fbe_mv,self.fbo_mv][y&1][x+(y//2)*self.hres]-self.black_level)/(self.white_level-self.black_level) def set_carrier(self,pre=1,per=1,w=1): self.tim.init(prescaler=pre,period=per) self.ch.pulse_width(w) def clear(self): self.fb.fill(self.black_level) self.syncs() def syncs(self): self.fb.fill_rect(0,0,self.h_blank[2],self.lines,self.blanking_level) self.fb.fill_rect(self.h_blank[0],0,self.h_blank[1]-self.h_blank[0],self.lines,self.sync_level) for y in range(self.v_blank_e[2]): inv = self.v_blank_e[0] <= y < self.v_blank_e[1] for x in range(self.hres//2): val = self.blanking_level if (self.h_blank[0] <= x < self.h_blank[1]) ^ inv: val = self.sync_level self.buf[y*self.hres//2+x] = val if not self.progressive: for y in range(self.v_blank_o[2]): inv = self.v_blank_o[0] <= y < self.v_blank_o[1] for x in range(self.hres//2): val = self.blanking_level if (self.h_blank[0] <= x < self.h_blank[1]) ^ inv: val = self.sync_level self.bo[y*self.hres//2+x] = val def x_dim(self): return self.hres-self.h_blank[2] def y_dim(self): return self.lines-(21 if self.progressive else 43) def mandelbrot(self,imax=8,p=0,s=2,julia=False,il=0,x0=None,y0=None,x1=None,y1=None,asm=True,julia_seed=0): x0 = self.h_safe[0] if x0 == None else x0 x1 = self.h_safe[1] if x1 == None else x1 y0 = self.v_safe[0] if y0 == None else y0 y1 = self.v_safe[1] if y1 == None else y1 for x in range(x0,x1): for y in range(y0,y1): c = (((x-x0)/(x1-x0-1)-.5)*2 + ((y-y0)/(y1-y0-1)-.5)*2j)*s+p z = c if julia: c = julia_seed if asm: i = a_mandelbrot(z,c,imax) else: for i in range(imax): if z.real*z.real+z.imag*z.imag > 4: break z = z*z+c else: self.set_pixel(x,y,il) continue if i == -1: self.set_pixel(x,y,il) else: self.set_pixel(x,y,i/imax) def demo(self,x0=None,y0=None,x1=None,y1=None): x0 = self.h_safe[0] if x0 == None else x0 x1 = self.h_safe[1] if x1 == None else x1 w = x1-x0 y0 = self.v_safe[0] if y0 == None else y0 y1 = self.v_safe[1] if y1 == None else y1 h = y1-y0 mx = x0 my = y0 import pyb import time acc = pyb.Accel() btn = pyb.Switch() p = self.get_pixel(int(mx),int(my)) pos = 0 zoom = 2 it = 16 julia = False jp = 0 self.mandelbrot(it,pos,zoom,julia,0,x0,y0,x1,y1,julia_seed=jp) def paddles(c): x = int(mx-.125*w) xw = w//4 y = int(my-.125*h) yw = h//4 y_0 = y0 y_1 = y1 if not self.progressive: y //= 2 yw //= 2 y_0 //= 2 y_1 //= 2 self.fbe.hline(x,y_0,xw,c) self.fbe.vline(x0,y,yw,c) self.fbe.hline(x,y_1,xw,c) self.fbe.vline(x1,y,yw,c) if not self.progressive: self.fbo.hline(x,y_0,xw,c) self.fbo.vline(x0,y,yw,c) self.fbo.hline(x,y_1,xw,c) self.fbo.vline(x1,y,yw,c) while 1: paddles(self.black_level) mx = min(x1-2,max(x0,mx*.98+(-acc.x()/24+.5)*w*.02)) my = min(y1-2,max(y0,my*.98+(acc.y()/24+.5)*h*.02)) paddles(self.white_level) p = self.get_pixel(int(mx),int(my)) self.set_pixel(int(mx),int(my),(p+.5)%1) pyb.delay(10) self.set_pixel(int(mx),int(my),p) if btn(): st = time.ticks_ms() nit = it*2 while btn(): if time.ticks_diff(time.ticks_ms(),st) > 1000: if acc.z()>0: nit = it*2 else: nit = "Julia" self.fbe.fill_rect(x0,y0,w,10,self.black_level) if not self.progressive: self.fbo.fill_rect(x0,y0,w,10,self.black_level) self.fbe.text(str(nit),x0+1,y0+1,self.white_level) if not self.progressive: self.fbo.text(str(nit),x0+1,y0+1,self.white_level) cp = (((mx-x0)/w-.5)*2+2j*((my-y0)/h-.5))*zoom if time.ticks_diff(time.ticks_ms(),st) > 1000: if nit == "Julia": julia ^= 1 jp = pos + cp pos = 0 zoom = 2 it = 16 else: it = nit else: pos += cp zoom *= .25 self.mandelbrot(it,pos,zoom,julia,0,x0,y0,x1,y1,julia_seed=jp)