Beispiel #1
0
def SetTapCmd(port, throughput_limit):
    """
    EstParser : Operación Manual de los Taps
    ========================================

    Uso :
       >> EstParser.py -manual

    La tarjeta es puesta en el modo de control remoto (deja de regular), perma-
    neciendo con el Tap activo al momento de la invocación de este comando.
    A continuación se inicia una sesión iteractiva, en la que se interroga por
    el tap a activar, el cual es un valor númerico, que si es válido, ordena el
    cambio al tap respectivo en la tarjeta. La sesión se termina cuando se
    responde 'x'.

    La numeración de los taps es a partir de 1, hasta la capacidad (total)de la
    tarjeta. Ordenados de mayor realación al de menor relación.

  """

    card = openCard(port, throughput_limit)
    card.EnterRemoteMode()

    while True:
        try:
            tap_str = input('\nTap a Activar : ')

            if tap_str == 'x':
                print('\nFin.')
                break

            tap = int(tap_str)

            if (tap < 0) or (tap > card.tapLimit):
                print('El número de tap debe ser > 0 y < %d.' % card.tapLimit)
                continue

        except ValueError as e:
            print("Valor numérico inválido, 'x' para abandonar.")

        except Exception as e:
            print(repr(e))

        # TODO Esta no es la mejor solución, el código del uC debe reformarse para
        # que en contol remoto tap = 0 implique la desconexión de todos los Taps.
        if tap != 0:
            # [TO DO]La siguiente instrucción fuerza el borrado de las banderas de
            # Sobrevoltaje y Subvoltaje, si se comenta la activación de los taps
            # solo puede efectuarse con la tensión de entrada en el rango correcto.
            #card.set('Tap Flags', 4)

            card.set('Tap Activo', tap + 0x0400)
            print('Se Activo el tap %d.' % tap)
        else:
            #card.set('Tap Flags', 5)
            card.set('Tap Activo', tap + 0x0500)
            print('Se desactivaron todos los Taps.')

    card.ExitRemoteMode()
    card.close()
Beispiel #2
0
def MonCmd(args, port, throughput_limit):
    u"""
    EstApp : Monitor de Tensión
    ===========================

    Uso :
      >> EstParser.py -mon [log_file]

    Presenta en la consola la medición y las estadísticas básicas de las
    tensiones LN y UV, a una taza de 1 seg.

     Simultáneamente registra el resultado en el archivo log_file (por
     defecto 'cycle_sampling.csv') de cada lectura.


  """

    card = openCard(port, throughput_limit)

    # Verifica los parámetros de trabajo :

    filename = args[2] if len(args) > 2 else 'cycle_sampling.csv'
    record_task = RecordReadingTask(card, filename)

    print('El registro de muestreo por ciclo se almacenará en %s\n' % filename)

    try:
        card.StartMeasure()
    except Exception as e:
        card.close()
        if type(e) != OTCProtocolError: print(e)
        sys.exit(1)

    record_task.start()

    if not card.measure.is_alive():
        print('Measure thread is not alive')

    try:
        while card.measure.is_alive():
            sleep(1.000)

            # Captura las lecturas de tensión :
            vLN = str(card.LN)
            vUV = str(card.UV)

            # Se requiere que las estádisticas no sean acumuladas en todo el
            # periodo de medición, sino con cada lectura :
            card.LN.stats.arm()
            card.UV.stats.arm()

            # Presenta los resultados en la consola :
            print('[L-N] %s, [U-V] %s, [%2d]' %
                  (vLN, vUV, card.LN.stats._count))

    except KeyboardInterrupt:
        pass

    record_task.stop()
    card.close()
Beispiel #3
0
def ScaleCmd(args, port, throughput_limit):
    u'''
  EstParser : Escala de Medición de las Tensiones
  ==============================================

  La escala de tensión depende la resistencias asociadas a las entrada de
  tensión alterna y el voltaje de referencia (potenciometro), según las
  fórmulas :
            Vref = 5V * 0.5 * P / (Rs + 0.5*P + k*Rd)
            Scale = Ri / Vref

  donde Rs es la resistencia en serie con el potenciometro (desde el positivo
  de la alimentación de 5V), P  es la resistencia del potenciometro, Rd es el
  valor de las resistencias de los divisores de tensión de la entrada y Ri es
  la resistenica en serie con la entrada de tensión alterna. El factor k es
  2/3 para todos los modelos excepto para el EstCard 23V0 en que es 1.

  El valor programado de la escala se obtiene con la orden
        >> EstParser.py -s

  y se modifica con la orden :
        >> EstParser.py -s nuevo_valor_de_la_escala.
  '''

    card = openCard(port, throughput_limit)

    if (len(args) < 3) or (args[2] == u'?'):
        print('  La Escala de Medición es %1.6f' % card.scale)

    else:
        try:
            scale = float(args[2])
            # if scale < 0 : raise Exception()
        except:
            print("<%s> no es un número.")
            sys.exit(1)

        try:
            card.scale = scale
            print("  Se reajusto la Escala de la Medición a %f" % card.scale)
        except ValueError as e:
            print(e.message)
            card.close()
            sys.exit(1)

    card.close()
Beispiel #4
0
def GainCmd(args, port, throughput_limit) :
  """
  EstApp : Ganancias de Compensación
  ==================================

  La tarjeta mide la tensión de dos fuentes, la primera mide la tensión
  entre las entradas L-N, la segunda dependiendo del modelo mide la tensión
  entre las entradas U-V o U-N. En el primer caso se tienen hasta 3 factores
  de compensación (calibración), para cada una de las fases L, U y V, en el
  segundo solo dos las fase L y U.

  Las ganancias o factores de compensación de las entradas L y U corrigen la
  ganancia de los divisores resistivos asociados a cada una de estas, en el
  caso de existir la entrada de tensión V esta se corrige con respecto al
  divisor de la entrada U.

  El valor nominal de las ganacias es de 50362 para las entradas L y U y
  admite valores entre 65535 y 0. Por otro lado para la entrada V su valor
  nominal es 0 y admite valores entre -128 a 127

  Uso :
     >> EstApp.py -[g|gL|gU|gV] [?]
     >> EstApp.py -[gL|gU|gV] valor_ganancia

  donde gL, gU, gV indican la ganancia de la entrada respecriva (L, U, V),
  el genérico g solo se utiliza para la lectura simultánea de las ganancias
  de las tres entradas.
  """

  card = openCard(port, throughput_limit)

  if (len(args) < 3) or (args[2] == '?') :

    if args[1] == '-g' :
      to_read = ['_gain%s' %x for x in card.inputs_available()]

    elif args[1][-1] in card.inputs_available() :
      to_read = ['_gain' + args[1][-1]]

    else :
      print('Error - El modelo de tarjeta %s no tiene la entrada %s.' %       \
                                      (card.id['hardware_Model'], args[1][-1]))
      sys.exit(1)

    for g in to_read :
      print(' La ganancia %s-N es %d.' %(g[-1], getattr(card, g)))

  else :
    if args[1] == '-g' :
      print('Error - Solo se permite ? para esta opción. ')
      sys.exit(-1)

    try :
      val = int(args[2])
      if (val < 0) or (val > 65535) : raise ValueError()
    except ValueError as e :
      print('Error : El valor %s no es número o esta fuera de rango.' %args[2])

    setattr(card, '_gain' + args[1][-1], val)

    print('  La ganancia de la entrada %s-N se rajusto a %d' %(args[1][-1], val))

  card.close()
Beispiel #5
0
def TimersCmd(args, port, throughput_limit):
    """
    EstParser : Tiempos de Encendido y Corte
    ========================================

    Uso :
       >> EstParser.py -t [?]
       >> EstParser.py -t [ off | corte | apagado | on | encendido ]
       >> EstParser.py -t tipo tiempo [por] [subtension | sobretension]
       >> EstParser.py -t tipo tiempo [por] tipo_evento Valor_del_Tiempo


    Permite leer los tiempos de corte y encendido por y desde sobretensión y
    subtensón.

    La primera forma presenta todos los tiempos, la segunda los restringe
    según el tipo de tiempo, i.e. solo a los de corte (opciones off, corte,
    apagado),  o solo a los de encendido (opciones on, encendido).

    La tercera restringe la presentación a un solo tiempo, donde tipo tiempo
    es cualquiera de las opciones [ off | corte | apagado | on | encendido] y
    el tercer argumento define el evento que se temporiza (subtensión o sobre-
    tensiòn).

    La cuarte es similar a la tercera pero ajusta el valor del tiempo por el
    especificado en Valor_del_Tiempo, el cual debe ser el valor númerico del
    tiempo expresado en segundos.

  """

    if (len(args) < 3) or (args[2] == '?'):
        card = openCard(port, throughput_limit)
        for s1 in ['Apagado por', 'Encendido desde']:
            for s2 in ['Subtensión', 'Sobretensión']:
                t_name = 'Tiempo de %s %s' % (s1, s2)
                print('  %-38s = %0.1f seg' % (t_name, card.get(t_name) / 60))

        card.close()
        sys.exit(0)

    elif args[2].lower() in ['corte', 'apagado', 'off']:
        t_name = 'Tiempo de Apagado por '

    elif args[2].lower() in ['encendido', 'on']:
        t_name = 'Tiempo de Encendido desde '

    else:
        print('Error : "%s" no es una opción correcta.' % args[2])
        print('Pruebe la opción -h -t para ver los detalles.')
        sys.exit(1)

    if (len(args) > 3) and (args[3] in ['por', 'desde']):
        args.pop(3)

    if (len(args) < 4) or (args[3] == '?'):
        s1 = t_name
        for s2 in ['Subtensión', 'Sobretensión']:
            t_name = u'%s%s' % (s1, s2)
            print('  %-38s = %0.1f seg' % (t_name, card.get(t_name) / 60))
        card.close()

    elif args[3].lower() == 'subtensión':
        t_name += 'Subtensión'

    elif args[3].lower() == u'sobretensión':
        t_name += u'Sobretensión'

    else:
        print('Error : "%s" no es una opción correcta.' % args[3])
        print('Pruebe la opción -h -t para ver los detalles.')
        sys.exit(1)

    if (len(args) < 5) or (args[4] == '?'):
        card = openCard(port, throughput_limit)
        val = card.get(t_name)
        print('%s = %0.1f seg.' % (t_name, val / 60))
        card.close()
        sys.exit(0)
    else:
        try:
            val = float(args[4])
        except:
            print("Error : %s no es un número." % args[4])
            sys.exit(1)

        if (val < 0) or (val > 65535 / 60):
            print("Error : %s esta fuera de rango [0 a %6.2f seg.]." %
                  (args[4], 65535 / 60))
            sys.exit(1)

        card = openCard(port, throughput_limit)
        card.set(t_name, int(val * 60))
        card.close()

        print("Se reajusto el %s a %0.1f seg." % (t_name, val))
Beispiel #6
0
def BackupCmd(args, port, throughput_limit) :
  """
  EstApp : Resguardo de la configuración
  ======================================

  El uso en general es :
     >> EstApp.py -b [-opcion_de_formato [opcion_Archivo_de_Respaldo]]

  en particular  :
     >> EstApp.py -b [-mch | -intelhex | -source | -dump [<backup_filename>] ]
     >> EstApp.py -b -bin <backup_filename>]

  Lee toda la configuración y la presenta o almacena (opcionalmente) en un archivo.
  (Es decir todo el contenido de la EEPROM del microcontrolador).

  Las opciones de formato son :

     Tabular (opción -dump)
        Presentación de forma simple del contenido, de 16 bytes por linea
        separados por espacios, con una primera columna con la dirección
        inicial de los bytes de la misma.

     Microchip .mch (opción -mch)
        Presentación del contenido en forma ordenada un byte por linea.

     IntelHex (opción -intelhex)
        Presentación del contenido en el formato IntelHex.

     C (opción -source)
        Genera texto compatible con el compilador C XC8, para definir el
        contenido de la EEPROM (i.e. la serie de instrucciones EEPROM_DATA
        que define el contenido respectivo).

     Binario (opción -bin)
        Genera un archivo binario (con el nombre del argumento adicional),
        con el contenido.

  El nombre del archivo de resguardo es opcional, en todos los casos excepto
  en el formato binario para la cual es obligatoria.

  Ejemplos :
      - Respaldo de la configuración y presentación solo en la consola,
        en el formato simple :
          >> EstApp.py  -b  -dump

      - Respaldo de la configuración en el archivo 'respaldo.txt' en el
        formato INTELHEX :
          >> EstApp.py  -b  -intelhex  respaldo.txt

"""
  card = openCard(port, throughput_limit)

  if len(args) > 4 :
    print('Advertencia : Demasiados argumentos.\n')

  arg = [card.eeprom]
  arg.extend(args[2:4])

  try :
    backup_txt = BackupData2str(*arg)
  except AttributeError as e :
    print(e.message)
    sys.exit(1)
  except IOError as e :
    print(e.args[1])
    sys.exit(1)

  # Se presenta en la consola el contenido del archivo :
  print("Configuración Completa : \n")
  print(backup_txt)

  card.close()
Beispiel #7
0
def CalCmd(args, port, throughput_limit):
    """
  EstApp : Calibración
  =======================

  Uso :
     >> EstApp.py -cal | -calL | -calU |calV [conteo_inicial [duración]] [[Siglent SDM3055 IP] -Y}

    El principio de la calibración consiste en medir el promedio de la tensión
    tanto por la tarjeta EstCard, como en un instrumento de referencia, para
    a continuación calcular los valores de ganancia de cada fase para igualarla
    a la del instrumento de referencia.

    El procedimiento de calibración, se inicia con una cuenta regresiva, al
    final de la cual se inicia el cálculo del promedio de la tensión por la
    tarjeta EstCard, simultáneamente debe iniciarse el registro de esta
    por el instrumento de referencia.

    El intervalo de tiempo durante el cual se realiza el cálculo del promedio
    de la tensión, se señala por una segunda cuenta regresiva, al final de la
    cual termina el cálculo del promedio de la tensión y deberá detenerse el
    registro en el instrumento de referencia.

    En una tercera etapa, el programa interroga al usuario por la medición del
    valor promedio de la tensión, cuando se ingrese el valor, se calcularán las
    ganancias respectivas y se interroga al usuario por su aprobación para
    proseguir con su modificación.

    Como instrumento de referencia, se pueden utilizar diversas series de
    multímetros Fluke con capacidad de registro (tecla [MAX MIN]), el inicio
    del registro se realiza pulsando la tecla [MAX MIN], para detener
    (congelar) el registro se pulsa la tecla [HOLD], el valor del promedio
    se puede obtener pulsando la tecla [MAX MIN] hasta que aparezca la leyenda
    AVG en la pantalla.

    La calibración se puede realizar independientemente en cada fase (opciones
    -calR, -calS, calT), o simultáneamente en las tres fases (opción -cal), no
    obstante en este caso deberá medirse la misma tensión en las tres fases, lo
    que implica que deben estar conectadas entre sí. En cualquier caso, la
    tensión de calibración siempre es la tensión Fase-Neutro.

    Los tiempos de las cuentas regresivas se pueden definir por medio de dos
    números opcionales seguidos de la opción (-cal, -calR,...,etc.), el
    primero (conteo_inicial) de los cuales es el tiempo (en segundos) de la
    cuenta regresiva para iniciar la medición y el segundo el de la cuenta
    regresiva de la duración del muestreo.

    Se puede utilizar un instrumento de referencia conectado a la red, su IP
    debe ir como parámetro final y solo se aceptan direcciones IP numéricas.
    A la fecha solo el multimetro SDM3055 es soportado.

    En el caso de utilizarse un instrumento de referecnia se puede utilizar la
    opción -Y, para saltarse la autorización de la calibración.
  """

    # Reconoce si el último parámetro es una dirección IP :
    skip = args[-1] in ['-Y', '-y']
    if skip: args.pop(-1)

    if is_IP(args[-1]):
        # Reconoce el instrumento de referencia :
        from . import SDM3055
        ip = None
        try:
            ip = args.pop(-1)
            dmm = SDM3055.SDM3055(ip)
            ref_measure = SDM3055.VACMeasure(dmm)
            print('Calibrador Modelo %s, %s, Nº %s\n' %
                  (dmm.model, dmm.manufacturer, dmm.num_serie))
        except Exception as e:
            print(
                "Error al comunicarse con el instrumento de referencia (%s)" %
                ip)
            print('(%s)' % e.message)
            sys.exit(-1)
    else:
        ref_measure = None

    # Reconoce los parámetros restantes como la cuenta regresiva y duración de la
    start_count_down, length_count_down = GetCountLength(args)

    # Se inicia la comunicación con el dispositivo :
    card = openCard(port, throughput_limit)

    # Determina la fase de trabajo :
    phase = args[1][-1] if len(args[1]) > 4 else 'L'

    # Comprueba si la fase de trabajo existe en la tarjeta :
    if not phase in card.inputs_available():
        print('La entrada %s no existe en la tarjeta de modelo %s' %
              (phase, card.id['hardware_model']))
        sys.exit(-1)

    # Se advierte al usuario de las conexiones necesarias :
    print('Calibración de la Fase %s-N (Entrada %s)\n' % (phase, phase))
    if (type(card) == EstCard1V0) or (phase == 'L'):
        print('Las entradas L y N deben estar alimentadas con la tensión ' \
              'nominal \ny simultánemente debe prepararse para medirse con ' \
              'el multímetro.\n')
        if phase != 'L':
            print('Además la entrada %s debe conectarse con la entrada L' %
                  phase)
            print('y la entrada %s con la entrada N.\n' %
                  ('V' if phase == 'S' else 'S'))

    else:
        print('Las entradas L y %s deben estar conectadas entre si, deben\n' \
              'alimentarse con respecto a la entrada N con la tensión nominal\n'\
              'y simultánemente debe prepararse para medirse.\n' % (phase))

    # Realiza la medición y su presentación :
    Measuring(card, phase, start_count_down, length_count_down, ref_measure)

    # Se interroga por el valor de la medición de referencia, solo cuando se
    # calibra la fase L(-N) y no existe un instrumento de referencia conectado :
    if ref_measure is not None:
        Vref = ref_measure.avg

    elif phase == 'L':
        while True:
            try:
                ans = input('\n\nValor de Referencia : ')
                if ans == 'x':
                    print('\nNo se programo el valor a elección del usuario.')
                    sys.exit(0)

                Vref = float(ans)
                break

            except ValueError as e:
                print("Error - Valor numérico inválido, 'x' para "                 \
                                                         "abandonar la calibración.")

            except Exception as e:
                print(repr(e))
    else:
        Vref = card.LN.rms

    # Se invoca al calibrador de la fase, de manera de acceder a la ganancia
    # actual y la nueva, de sus representaciones interna y la medición justo
    #realizada :
    try:
        cal = card.calibrator(phase, Vref)

    except ValueError as e:
        print('Error - No se puede continuar con la calibración.')
        print('%s' % e.message)
        card.close()
        sys.exit(1)

    # Se posponen los cambios ...
    try:
        print('\nEl valor actual %s del factor de calibración de la fase %s, ' \
              '\nse remplazará por (%s) \n' %(cal.old, phase, cal.new))

        while True and not skip:
            ans = input('Se acepta ?  [S/N]')
            if ans.lower() in ['s', 'si', 'n', 'no']: break

        # y se solicita la autorización para el cambio :
        if skip or (ans.lower() in ['s', 'si']):
            cal.commit()
            print('\nLa ganancia se reajusto.\n')
        else:
            print('\nNo se programo el valor a elección del usuario.\n')

        card.ExitRemoteMode()

    except OTCProtocolError:
        # En este punto el 'logger' reporto la descripción del error en la
        # consola y no hay nada que hacer.
        pass

    card.close()

    sys.exit(0)
Beispiel #8
0
def ModeCmd(args, port, throughput_limit):
    """
  EstApp : Atributos del Modo de Operación
  ========================================

  Uso :
     >> EstApp.py -m [?]
     >> EstApp.py -m nombre_atributo
     >> EstApp.py -m nombre_atributo valor_atributo

  La primera forma permite leer los atributos del modo de operación, que
  son :
   Selección de Entrada :
     Seleccionar la entrada de tensión usada para medir la entrada.
     Admite dos valores LN y UV.

   Realimentación :
     Activa o desactiva la entrada de tensión alternativa para la medicíon
     de la salida. Admite dos valores Actia e Incativa (alternativamente
     on/1 u off/0 respectivamente).

   Expansión :
     Habilita o Deshabilita la salida de expansión. Admite dos valores
     Activa e  Incativa (alternativamente  on/1 u off/0 respectivamente).

   Taps Superpuestos :
     Activa o desactiva el modo de operación de Taps Superpuestos.  Admite
     dos valores Activa e Incativa (alternativamente  on/1 u off/0
     respectivamente).

   Entrada de Coordinación :
   Salida de Coordinación  :
     Activa o desactiva la entrada y salida de coordinación entre tarjetas
     (sistema trifásico). Admite dos valores Activa e Incativa (alternativa-
     mente  on/1 u off/0 respectivamente).

  La segunda forma permite leer el estado de un atributo en particular, donde
  nombre_atributo es cualquiera de los anteriores.

  La tercera forma permite modificar el estado del atributo, en este caso
  valor_atributo, es uno de los valores admisibles.
  """

    # Si no se especifican argumentos adicionales, se presentan todas las
    # funciones del Modo :
    if (len(args) < 3) or (args[2] == u'?'):
        card = openCard(port, throughput_limit)
        print(
            'Las Funciones del Modo de Operación\nestán programadas según :\n')
        print('%s' % card.modeFlags)

        sys.exit(0)

    card = openCard(port, throughput_limit)

    # Como el nombre de la función del modo, es en general compuesta por mas de
    # de una palabra, su nombre estará definido por la concatenación de los
    # elementos de args desde el tercero (i.e.args[2]) hasta un número determi-
    # nado por el nombre mismo. Para identicarlo los elementos de args a partir
    # del tercero se concatenan para fomrar tuplas (nombre, valor) :
    #    name[n] = args[2] + ' ' + ... args[2+n]
    #   valor[n] = args[2+n+1] + ' ' + ... args[len(args) - 3]
    # y se prueban hasta encontrar la que sea correcta.
    name_value = [(u' '.join(args[2:3 + n]), u' '.join(args[3 + n:]))
                  for n in range(len(args))]

    # Es conveniente trabajar con los nombres en minúscula, flag_namens es un
    # diccionario que contiene los nombres estándar de las banderas vs el
    #nombre en minúscula :
    flag_names = dict([(n.lower(), n) for n in ModeFlags.functionNames()])

    for name, value in name_value:
        if name.lower() in flag_names.keys():
            # Obtiene el nombre real :
            name = flag_names[name.lower()]

            if value in ['?', '']:
                print('Estado de la función de %s' %
                      card.modeFlags.getStatusStr(name))
                card.close()
                return

            else:
                try:
                    setattr(card.modeFlags, card.modeFlags.getFunctionOf(name),
                            value)

                    print('La función de \'%s\' se modifico a %s' %
                          (name,
                           getattr(card.modeFlags,
                                   card.modeFlags.getFunctionOf(name))))
                    card.close()
                    return

                except ValueError as e:
                    print('%s' % e.message)
                    card.close()
                    sys.exit(1)

    # Si se alcanza este punto la línea e argumentos no pudo ser reconocida :
    print('Error : "%s" no tiene el formato correcto.' % (args[2:]))
    print('Pruebe la opción -h -m para ver los detalles.')
    sys.exit(1)
Beispiel #9
0
def OrderingTapCmd(args, port, throughput_limit) :
  """
    EstApp : Configuración del Orden de los Taps
    ============================================

    Uso :
       >> EstApp.py -o
       >> EstApp.py -o nuevo_orden

     La primero orden presenta en la consola el orden de activación de los taps
     cuando la tensión es ascendente.
     La segunda además modifica el orden de los taps, según la secuencia definida
     por nuevo orde.
     
     nuevo_orden se expresa como la secuencia de números, en que es el número de
     la salida (TAPx, x = 1,2,3 ...) en la que se reordena la activación de los 
     taps (siempre cuando la tensión es ascendente). 
     
     Se deben asignar la secuencia de activación a todos los Taps del modelo de 
     la tarjeta, independientemente si no se usan todos los taps.

     Orden válida para Versiones de Software 1V05 o superiores.
  """

  card = openCard(port, throughput_limit)

  #if card.id['software_kernel'] == 'CtrEst 1V0' :
  #  print('Error : Orden no válida para esta la versión de programa de la tarjeta.')
  #  sys.exit(1)

  seq_str = lambda x : ' '.join(['{:d}'.format(n) for n in x])

  std_order = (1,2,3,4,5,6,7,8,9,10,11,12)[:card.tapLimit]
  tap_order = card.tapOrder[:card.tapLimit]

  print(' Orden de los Taps :')
  print(('           %s' % seq_str(std_order)))
  print(('Anterior   %s' % seq_str(tap_order)))

  new_order = [int(n) for n in args[2:]]
  if len(new_order) > 0 :
    if len(new_order) != card.tapLimit :
      print(('Error - El número de taps definido no coincide con el del modelo de tarjeta (%d).' %card.tapLimit))

    elif any([(n < 1) or (n > card.tapLimit) for n in new_order]) :
      print(('Error - El número de órden de los taps excede el rango (1 - %d).' % card.tapLimit))

    elif any([new_order.count(n) > 1 for n in std_order]) :
      for n in std_order :
        if new_order.count(n) > 1:
          print(('Error - El número de órden (%d) de los taps esta repetido.' % n))

    else :
      # Se fuerza la desconexión de los Taps de lo contrario la tarjeta activa el nuevo tap sin
      # desconectar el antiguo :
      card.EnterRemoteMode()
      card.set('Tap Activo', 0x0500)
      
      card.tapOrder = new_order + list(range(card.tapLimit+1 , 12 + 1))
      new_order = card.tapOrder[:card.tapLimit]
      card.ExitRemoteMode()

      print(('Actual     %s\n' % seq_str(new_order)))
      print('Se cambio el orden de los taps.')

  card.close()