예제 #1
0
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
예제 #2
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
예제 #3
0
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
예제 #5
0
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
예제 #6
0
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
예제 #8
0
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)
예제 #9
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()
예제 #10
0
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
예제 #11
0
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()

    
예제 #13
0
파일: NTSC.py 프로젝트: pramasoul/pyb-ntsc
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)