Acuariofilia Madrid

Versión completa: Aula Arduino para principiantes.
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.
Hay bastante silencio. No sé si os interesan mis divagaciones sobre estos temas o andais muy perdidos para siquiera opinar.

Intento dar con la solución óptima para el dimeo de motores estudiando distintas alternativas.
De lo contrario una decisión adoptada a la ligera podría condicionar todo el diseño de CAO en una dirección que luego se demostrara inconveniente. Todos los esfuerzos por prevenir este tipo de errores de en las primeras fases de un diseño software son siempre muy rentables. Hasta ahora todas las soluciones al problema del dimeo de motores tienen alguna que otra pega y por eso me ha costado decidirme.

También me ha costado decidirme porque últimamente estoy reconsiderando el tema de Arduino DUE. Ahora creo que para una instalación de un gran acuario tener un controlador central muy completo puede estar muy bien bien, pero en algunas instalaciones domésticas estoy seguro de que mucha gente preferirá optar por pequeños controladores más baratos y que hagan solo algunas cosas.

Siempre pensé que CAO terminaría tirando por Arduino DUE pero en parte gracias a vosotros, ya no lo tengo tan claro. Una habitación con varios acuarios que tengan distintas necesidades de control cada uno puede necesitar un sistema distribuido en lugar deun controlador molótico (de un solo bloque).

Creo que lo único que necesita estar centralizado es el interfaz de control. Voy a completar la nueva version de CAO1, pero en ella me gustaría incluir módulos aprovechables para otro tipo de arquitecturas.
Estoy repensando todo el diseño de CAO y no solo estoy explorando las posibilidades de DUE, también estoy explorando las posibilidades de las placas baratitas como el Arduino Pro Mini 328.

No voy a usar un Timer que solo funcione en DUE ni exclusivo para una placa Arduino en especial. Voy a buscar un dimeo de motor compatible con una amplia variedad de placas y en especial con las más baratitas.

Hay una página interesante.
http://arduino-info.wikispaces.com/Ardui...iderations

He realizado más pruebas. Concretamente he dimeado en Arduino UNO un motor en el pin 9 (los pines 9 y 10 solo entrearían en contacto con la librería servo) y he realizado un programa que realiza el dimeo de un motor con las 5 posibles frecuencias que Arduino puede facilitar en este pin. Creo que me voy a decir por esto.

Supongo que lo mejor es dejar la opción de que la frecuencia de dimeo pueda ser configurada. En mi caso las frecuencias extremas para este pin son 31Khz y 30 Hz. Ambas frecuencias resultan inaudibles mientras que las intermedias provocan ruido. Esta solución es incompatibles con servos pero funcionaría en una amplia variedad de placas Arduino. Os pongo el código por si lo queréis probar.

Código:
#include <Arduino.h>

int led        = 9;
int brightness = 0;

// *****************************************************
// Varia la frecuencia de PWM en los pines 9 y 10
// (No es compatible con el uso de las librerías servo)
// *****************************************************
// Modo           Divisor         Frecuencia
// 0x01            1               31372.55
// 0x02            8               3921.16
// 0x03            64              490.20   <--DEFAULT
// 0x04            256             122.55
// 0x05            1024            30.64
// *****************************************************
void SetPwmFreqP9P10(byte mode) {
    if (mode<0x01 || mode>0x05) return;
    TCCR1B = TCCR1B & 0b11111000 | mode;
    Serial.print("Modo=");
    Serial.println(mode);
}

// ***************************
void setup()  {
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

// ***************************
void loop()  {  
    for (byte m=0x1; m<=0x5; m++){
      analogWrite(led, 0);
      delay(6000);
      SetPwmFreqP9P10(m);
      for (int brightness=0; brightness<=255; brightness++){
          analogWrite(led, brightness);
          Serial.println(brightness);
          delay(100);
      }
    }
}
Antonio perdidos no, pero unos cuantos creo que nos dejamos guiar y estamos detrás de tus progresos. Pero sin mucho que aportar preferimos no ensuciar el post con trivialidades.
efectivamente,
Yo entro a diario a leer las novedades.

Gran ayuda para todos Antonio.
Un saludo
Antonio, que no te se pase por la cabeza que tu post no es interesante, pero como dicen los compañeros, si no te tenemos nada que aportar, mejor no ensuciar el post
Al igual que los compañeros opino lo mismo, aparte que ando bastante liado ahora, de hecho ni he podido probar el modulo PWM que compre.

Saludos.
Se ve que estamos todos algo liados.

Os comento que en el tema de cambiar la frecuencia de dimeo en Arduino, conviene saber como están ligados los pines con capacidad PWM a los distintos Timers de la placa y que funciones de Arduino hacen uso de los diferentes Timers para evitar conflictos.

Pese a que CAO1 está pensado para Arduino MEGA 2560, los módulos que lo componen deberían tener la máxima compatibilidad con diferentes placas. Al final he tenido que hacer un estudio de los pines para PWM y las funcionalidades que se usan en ellos para prevenir futuros conflictos. Necesito saber que pines se podrían usar para un PWM con frecuencia modificada minimizando conflictos.

Las tablas que pondré a continuación tendrán tres columnas que son:
Timers, Pines para PWM y [Funcionalidades que dependen de ese Timer]

Para Arduinos AVR con chip ATmega168 y ATmega328 o similares.
Es decir, para Arduino Uno, Nano,  etc. tenemos la siguiente situación.
3 Timers, 6 pines PWM
Timer0: 5,6 [millis(), delay(),...]
Timer1: 9,10 [Servo library]
Timer2: 11,3 [tone()]

Para Arduinos AVR con chip ATmega1280 y ATmega2560 o similares
Es decir, para Arduino Mega1280, Mega2560, MegaADK, etc. Tenemos
6 Timers, 15 PWM
Timer0: 4,13 [millis(), delay(),...]
Timer1: 11,12
Timer2: 9,10 [tone()]
Timer3: 2,3,5
Timer4: 6,7,8
Timer5: 46,45,44 [Servo library]


CAO1 usa Arduino MEGA 2560 así que para variar la frecuencia no podemos usar los pines 9 y 10 porque afectaria a la función tone() que usamos para el zumbador, los pines 4 y 13 porque afectaría a las funciones millis(), delay(), etc.

En Arduino UNO por la misma razon los pines que no podríamos usar son 11,3 que se usan para tone() y 5,6 que se usan para millis() y delay(). En Arduino uno los únicos pines donde podríamos variar la frecuencia de PWM es en los pies 9,10 que ya hemos dicho no serían adecuados en Arduino Mega.

Dentro de lo posible, (En Arduino UNO todo no se puede) habrá que intentar reservar los pines que se usan para Servo library.

Además de lo dicho tenemos que tener en cuenta que los temporizadores comparten PWM para más de un pin. Si pretendieramos dimear en CAO uno un motor a 30hz para suprimir el zumbido usando para ello el pin 12 que lo tenemos libre, la luz blanca que tenemos situada en el pin 11 tendría un efecto molesto porque a 30 hz se percibe la vibración de luz por PWM cuando se reduce la intensidad.

Las dos tablas que he puesto conviene tenerlas presente.


Desconozco la situación para Arduino DUE pero tiene solo 12 salidas para PWM.
Lo lógico es que sea una situación similar a la de Arduino Mega para no introducir incompatibilidad ya que el número de pines y su disposición son muy similares.
He buscado la información pero no viene ninguna explicada en plan sencillito como yo acabo de presentarlo y lo que he encontrado no me saca de dudas.
The Timer Counter blocks of Arduino Due's AT91SAM3X8E
https://github.com/ivanseidel/DueTimer/b...Counter.md

Para poder hacer ampliaciones sin tanto problema habría que prescindir de intentar hacerlo absolutamente todo desde un solo controlador.
(21-11-2014, 10:38 PM)Antonio Castro escribió: [ -> ]Hay bastante silencio. No sé si os interesan mis divagaciones sobre estos temas o andais muy perdidos para siquiera opinar.

En mi caso si que ando perddo ... pero por mi falta de conocimiento en programación.
Sabes que estoy en ello Smile, pero no dejo de ver el post para ver loq que se cuece aqui ...

Como decia la canción... No pares, sigue, sigue No pares, sigue, sigue -notworthy.gif-notworthy.gif
Hola Antonio.

Yo este tema no opino mucho porque no tengo ni idea de programación. De hecho le cogí algo de asco jejeje.

Sin embargo te digo que si voy leyendo lo que vais poniendo y las estadísticas del foro dicen que la gente tiene interés en este tema, así que te invito a que sigas divagando como bien dices, pues es una fuente de conocimiento para todos.
Gracias Alvaro por la información.

En Internet hay mucha información, pero con mucha frecuencia miras en un par de sitios algo y te haces una idea equivocada. De hecho, yo volví a mirarme el tema después de un primer intento para añadir un modulito a CAO1 para gestionar la velocidad motorcitos de ventilación suprimiendo el zumbido que suele aparecer. Me dí cuenta de que la luz blanca vibraba.

Mirando con mas detenimiento me di cuenta que la asignación de los pines PWM a los temporizadores no mantiene la compatibilidad entre Arduino UNO y Arduino MEGA. Tengo que cambiar el diseño de ese módulo para que contemple toda la problemática de compatibilidades. Eso es mucho mejor que obligar a todo el mundo usar un determinado pin para hacer dimeo de motores en CAO1.

Este es un tema algo delicado, difícil de explicar y dudo que mis divagaciones anteriores fueran explicadas por mí con suficiente claridad. Por ello he programado una demo con propósito didáctico para que cualquiera que carezca de conocimientos de programación y tenga alguna necesidad de dimear motores pueda usarlo para hacer sus pruebas de hardware previas y así poder elegir así el pin y la frecuencia en función de el resto del hardware que tenga instalado en su placa y también en función de la placa. Por ejemplo: yo para solucionar el problema de la vibración el el canal de luz blanca pensé que tenía que cambiar a otro pin el ventilador, pero la vibración aparece por usar una frecuencia baja de 30 hz. Existe otra posible solución que es usar un ultrasonido de 30Khz para dimear el motor. Se suprime igualmente el zumbido en el motor y el dimeo de la luz blanca es aparentemente normal aunque en realidad la frecuencia de PWM ha sido cambiada a 30Khz. Con un recurso tan crítico es mejor no forzar soluciones concretas para permitir el máximo de flexibilidad.


Código:
/*****************************************************************************************************
  (C) Antonio Castro nov-2014
  Licencia de uso Creative Commons

DESCRIPCION:
  Programa para realizar cambios de frecuencia PWM y comprobar los efectos colaterales y conflictos que
  ello pueda ocasionar.

  El programa asumirá que tenemos leds conectados en los pines 3,5,6,11 que se inicializaran con un
  valor de dimeo bajo y constante. De esta forma podrémos verificar si al usar una frecuencia de dimeo de
  valor bajo en algún otro pin (por ejemplo para un ventilador) se produce algún efecto indeseable
  (vibración de la intensidad del led) en alguno de los leds en pines 3,5,6,11. Esto ocurrirá si elegimos
  un pin que use el mismo Timer para PWM que cualquiera de los pines ya usados para el dimeo de leds.

  El programa también asumirá que tenemos un zumbador piezo eléctrico conectado en el pin 2 y verificamos
  como se afecta el zumbido constante al usar ese mismo pin 2 o algún pin cuyo Timer interfiera en la
  función tone(). Los pines que entrarán en conflicto con la funcion tone() serán diferentes dependiendo
  del tipo de placa.

  El programa detectará, a los efectos anteriores descritos, a que grupo de placas pertenece la placa con
  la que estamos trabajando. Mostrará la información relativa a Timers y pines relativa a la placa que
  estemos usando con el fin de que el usuario pueda elegir el número de pin adecuado a lo que se desee probar.
  Bastará introducir  el número de pin adecuado al tipo de prueba que quiera hacer, para ello el programa
  ha de ejecutarse activando el monitor Serial.

  Para cada pin que se introduzca, se probarán todas las frecuencias PWM diponibles para ese Pin y se mostrará
  información completa relativa al Timer y frecuencia usada para la correcta interpretación de los resultados.

  Si el usuario introduce un pin que no tiene asociada funcionalidad PWM, se informará de esa circunstancia y
  no hará nada.

  Si el usuario introduce un número de pin asociado al Timer0 se afectará la función delay() y la ejecución del
  programa se acelerará o ralentizará dependiendo de la frecuencia que se esté verificando

  El programa puede venir bien para probar la idoneidad de la elección de un determinado pin y una determinada
  frecuencia de PWM en una salida que deseemos probar con un motor para dimearlo, asi como para chequear los
  posibles conflictos software y hardware. Para ello, introduzca el pin donde quiera usar dimeo del motor a una
  frecuencia de dimeo diferente de la que viene por defecto.

  La eleccion de los pines 3,5,6,11 para el dimeo de leds y la eleccion del pin 2 para el zumbador se corresponde
  con la configuración de CAO1 en una placa A. MEGA 2560 porque es la que me interesaba probar a efectos de valorar
  donde enchufar el motor para dimearlo en CAO1. Si desea hacer el test asumiendo otra configuración, convendrá
  que haga los cambios correspondientes en la asignacion de pines inicial. Ademas de los correspondientes defines
  y acuérdese de inicializar correctamente las salidas que desee verificar a efectos de posibles conflicos.
****************************************************************************************************************/


#include <Arduino.h>

// **** Pines correspondientes a la configuración que deseamos probar.
#define Pin_DimLedAzul       3      // Pin dimeo luz azul, (nocturna y refuerzo luz dia)
#define Pin_DimLedRojo       5      // Pin dimeo luz roja  (crepuscular temprana y ocaso tardio)
#define Pin_DimLedAmbar      6      // Pin dimeo luz ambar (crepuscular tardía y ocaso temprano)
#define Pin_DimBlanco       11      // Pin dimeo luz blanca calido (luz principal diaria)
#define Pin_Buzz             2      // Pin de activacion del Zumbador

int brightness = 0;

// *** 168 and 328 Arduinos ***
// For Arduino Uno, Nano, Micro Magician, Mini Driver, Lilly Pad and any other board using ATmega 8, 168 or 328
#if defined(__AVR_ATmega168__) ||defined(__AVR_ATmega168P__) ||defined(__AVR_ATmega328P__)
  #define ATmega_168_168P_328P 
// *** Mega 1280 & 2560 ***
// For Arduino Mega1280, Mega2560, MegaADK, Spider or any other board using ATmega1280 or ATmega2560
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  #define ATmega_1280_2560 
#endif

#define MAX_BUFF_IN 5
char _BUFF_IN[MAX_BUFF_IN];
uint16_t KHZ=16000; // Khz. ClockFreq

// ****************************************************************
char *ReadLn() {
   // Maxima longitud del buffer de recepcion.
   unsigned i=0, j;

   if (Serial.available()==0){  
       return "";
   }
   // Se recibió algo pero puede que aun no esten disponibles
   // todos los caracteres enviados. Por eso forzaremos
   // una espera de 50 milisegundos. (Optimizable)
   delay(50);
   // Puede llegar con mucha basura previa.
   if (Serial.available()>=MAX_BUFF_IN){
      // Vaciar Buffer de entrada (demasiados caracteres).
       while (Serial.available()){
          Serial.read();
       }
       Serial.print("Linea de entrada muy larga.");
       return "";
   }

   // Queremos que la cadena se rellene hasta
   // MAX_BUFF_IN-2 para que en el carácter MAX_BUFF_IN-1
   // podamos meter el terminador \0
   while (Serial.available() && i<MAX_BUFF_IN-1) {
      _BUFF_IN[i]=Serial.read();
      i++;
      // La recepcion tiene una latencia, se produce a traves de una interrupcion,
      // que a lo mejor se ejecuta un poco despues del Serial.available() por lo que
      // el dato no entraría. Por eso hacemos una pequeña espera
      delayMicroseconds(500);
   }
   // Suprime el '\n' recibido al cinal y Termina la cadena recibida en '\0'
   for (j=i; j<sizeof(_BUFF_IN); j++)
        _BUFF_IN[j]='\0'; // Terminar en '\0' y limpiar restos de lecturas anteriores
   return _BUFF_IN;
}

// ***********************************************
// ********** Analisis de comandos ***************
// ***********************************************
int GetPinFromSerial(){
   char *Str;
   boolean CommandOk=false;

   Str=ReadLn();
   if (strlen(Str)>0){
       Serial.print("(");
       Serial.print(Str);
       Serial.println(")");
   }
   return atoi(Str);
}

// ********************************************************************
int TimerPWM_Pin(int Pin){

Serial.print("Pin=");
Serial.println(Pin);
#if defined(ATmega_1280_2560) // MEGA, ...
    switch(Pin){
        case 4:
        case 13:
            return 0;
        case 11:
        case 12:
            return 1;
        case 9:
        case 10:
            return 2;
        case 2:
        case 3:
        case 5:
            return 3;
        case 6:
        case 7:
        case 8:
            return 4;
        case 44:
        case 45:
        case 46:
            return 5;
        default: return -1;
    }
#endif
#if defined(ATmega_168_168P_328P) // UNO, ...
    switch(Pin){
        case  5:
        case  6:
            return 0;
        case  9:
        case 10:
            return 1;
        case 11:
        case  3:
            return 2;
        default: return -1;
    }
#endif
}

// ********************************************************************
int SetPwmFreq(int Timer, byte setting, boolean Verbose) {
    Serial.println("====================================================");
    if (setting<0x01 || setting>0x05){
        if (Verbose){
            Serial.print(" Setting=");
            Serial.println(setting);
            Serial.println("Setting fuera de rango");
        }
        return -1;
    }
    switch(Timer){
        case 0:
            TCCR0B = TCCR0B & 0b11111000 | setting;
            break;
        case 1:
            TCCR1B = TCCR1B & 0b11111000 | setting;
            break;
        case 2:
            TCCR2B = TCCR2B & 0b11111000 | setting;
            break;            
#if defined(ATmega_1280_2560) // MEGA, ...
        case 3:
            TCCR3B = TCCR3B & 0b11111000 | setting;
            break;
        case 4:
            TCCR4B = TCCR4B & 0b11111000 | setting;
            break;
        case 5:
            TCCR5B = TCCR5B & 0b11111000 | setting;
            break;
#endif
        default:
            Serial.print("Timer=");
            Serial.println(Timer);
            Serial.println("Timer fuera de rango");
            return -1;
    }
    // El cambio en el Timer ya está hecho, pero vamos a
    // poner amplias trazas con caracter didáctico.
    unsigned int FrecBase;
    unsigned int Divisor;
    if (Timer==0){
        FrecBase=62500;
    }
    else{
        FrecBase=31373;
    }
    if (Timer==2){
        switch(setting){
            case 0x1:
                Divisor=1;
                break;
            case 0x2:
                Divisor=8;
                break;
            case 0x3:
                Divisor=32;
                break;
            case 0x4:
                Divisor=64;
                break;
            case 0x5:
                Divisor=128;
                break;
            case 0x6:
                Divisor=256;
                break;
            case 0x7:
                Divisor=1024;
                break;
            default:
                Divisor=-1;
                break;
        }
    }
    else{
        switch(setting){
            case 0x1:
                Divisor=1;
                break;
            case 0x2:
                Divisor=8;
                break;
            case 0x3:
                Divisor=64;
                break;
            case 0x4:
                Divisor=256;
                break;
            case 0x5:
                Divisor=1024;
                break;
            default:
                Divisor=-1;
                break;
        }
    }
    if (Divisor==-1){
        Serial.println("Error de programación calculaindo el divisor");
        return -1;
    }
    if (Verbose){
        Serial.print("Timer=");
        Serial.print(Timer);
        Serial.print(" Setting=");
        Serial.print(setting);
        Serial.print(" Divisor=");
        Serial.print(Divisor);
        Serial.print(" Frec=");
        Serial.println(FrecBase/Divisor);
    }
    return 0;
}

// *************************************
int DefaultPwmFreq(int Timer){
    if(Timer==2)return 4;
    else return 3;
}


// *************************************
int SolicitarNuevoTest(){
  int PinMotor;

  Serial.println("");
  Serial.println("*** Deteccion Hardware ***");
#ifdef ATmega_1280_2560
  Serial.println("Mega 1280 & 2560 ==> Mega1280, Mega2560, MegaADK, Spider"); 
  Serial.println("Timer0: 4,13  [millis(), delay(),...]");
  Serial.println("Timer1: 11,12 ");
  Serial.println("Timer2: 9,10  [tone()]");
  Serial.println("Timer3: 2,3,5");
  Serial.println("Timer4: 6,7,8");
  Serial.println("Timer5: 46,45,44 [Servo library]");  
#endif
#ifdef ATmega_168_168P_328P
  Serial.println("168 and 328 Arduinos ==> UNO, Nano, Micro Magician, Mini Driver, ...");
  Serial.println("Timer0: 5,6   [millis(), delay(),...]");
  Serial.println("Timer1: 9,10  [Servo library]");
  Serial.println("Timer2: 11,3  [tone()]");
#endif
  Serial.print("Clock=");
  KHZ=F_CPU/1000;
  Serial.print(KHZ);
  Serial.println("Khz");
    Serial.println("");
    Serial.println("INTRODUCIR PIN DIMEO MOTOR");
    do{
        PinMotor=GetPinFromSerial();
    } while (PinMotor==0);
    return PinMotor;
}


// ***************************
void setup()  {
  Serial.begin(9600);
  // **** inicializar las salidas que sea necesarias para nuestra configuracion *****
  pinMode(Pin_DimLedAzul, OUTPUT);
  pinMode(Pin_DimLedRojo, OUTPUT);
  pinMode(Pin_DimLedAmbar, OUTPUT);
  pinMode(Pin_DimBlanco, OUTPUT);
  pinMode(Pin_Buzz, OUTPUT);
  int brightness=70; // PWM bajo
  analogWrite(Pin_DimLedAzul, brightness);
  analogWrite(Pin_DimLedRojo, brightness);
  analogWrite(Pin_DimLedAmbar, brightness);
  analogWrite(Pin_DimBlanco, brightness);
}

// ***************************************************
void loop()  {  
    int Tim, PinMotor, brightness;

    PinMotor=SolicitarNuevoTest();
    if (PinMotor==-1){
        Serial.println("No PWM available on this pin");
        return;
    }
    else{
        pinMode(PinMotor, OUTPUT);
        Tim=TimerPWM_Pin(PinMotor);
        for (byte m=0x1; m<=0x5; m++){
          analogWrite(PinMotor, 0);
          tone( Pin_Buzz, 700);
          if (SetPwmFreq(Tim, m, true) ==-1 ){
            return;
          }
          for (int brightness=0; brightness<=255; brightness+=5){
              analogWrite(PinMotor, brightness);
              if (brightness%14){
                  Serial.print(brightness);
                  Serial.print(", ");
              }
              else{
                  Serial.println("");
              }
              delay(50);
          }
          Serial.println("");
          noTone( Pin_Buzz);
          delay (1000);
        }
        SetPwmFreq(Tim, DefaultPwmFreq(Tim), false ); // Recuperar setting por defecto
        Serial.print("Recuperada la configuracion por defecto para Timer");
        Serial.println(Tim);
    }
}
De hecho, es el segundo tema más visitado con 27097, por lo que Antonio, las cosas las estas haciendo muy muy bien.
Yo me pierdo en tantos datos y sistema, la verdad que a mí, se me escapa, pero interesante es un rato.







1 saludo
(28-11-2014, 01:50 AM)Gwendal escribió: [ -> ]De hecho, es el segundo tema más visitado con 27097, por lo que Antonio, las cosas las estas haciendo muy muy bien.
Yo me pierdo en tantos datos y sistema, la verdad que a mí, se me escapa, pero interesante es un rato.

1 saludo

Gracias por esa información estadística que desconocía, espero que cada vez más gente se anime a compartir sus ideas, sus proyectos y sus conocimientos. Smile
Antonio, esas estadísticas la puedes ver tu mismo en el index del foro, en la parte superior.
Temas más vistados, mayor reputación de usuarios, temas recientes, etc.

saludos!!!
(28-11-2014, 11:58 AM)Jec escribió: [ -> ]Antonio, esas estadísticas la puedes ver tu mismo en el index del foro, en la parte superior.
Temas más vistados, mayor reputación de usuarios, temas recientes, etc.

saludos!!!
Ok Gracias.
Antonio, ¿que ventajas tiene usar el TIP120 a el TIP141?, te lo digo porque ayer en un ratin que tenia libre me dio por probar los TIP141 y los ventiladores que tengo instalados en mi pantalla y no hace el ruido de interferencia como nos muestras con el TIP120.

Saludos.
Uno de los motivos por los que agradezco la interactividad es porque siempre aprendo cosas nuevas. En particular en temas de hardware.

No me hagas mucho caso David, pero creo recordar que hace tiempo que hice una prueba con TIP141 y un ventilador y no me funcionó. Lo cierto es que he intentado averiguar cual puede ser la diferencia entre ambos transistores en lo que respecta a cargas inductivas y no la he localizado.

He visto multitud de ejemplos de dimmers de leds con el TIP141 pero ninguno para cargas inductivas. Para cargas inductivas lo que he visto usar es el TIP120. Pese a ello nunca tuve la seguridad de que no se pudieran usar.

Yo supongo que en el resultado final puede influir mucho la frecuencia usada y la impedancia de la carga inductiva. Existe un parámetro que es la velocidad de conmutación. Switching Time. Puede venir especificado en alguna tabla donde se menciona un test realizado en unas determinadas condiciones de carga de frecuencia y de porcentaje del ciclo de trabajo PWM (duty cicle) o tambien en una gráficas que no acierto a interpretar. Yo creo que la clave ha de estar en ese parámetro de tiempo de conmutación.

Supongo que una velocidad de conmutación algo lenta para cierta carga puede amortiguar el zumbido y si es una velocidad de conmutación muy lenta para esa frecuencia supongo que puede impedir completamente el funcionamiento del dimeo. Lo que te menciono es más por intuición que por otra cosa.

Si te funciona aceptablemente el motor con el TIP141 y sin zumbido con ese ventilador yo no me molestaría en cambiar de transistor.

Lo que tienes que tener en cuenta es que si algún día cambias de ventilador y deja de funcionarte podría ser porque el nuevo ventilador tenga una impedancia más alta y requiera un transistor diferente.

En los datasheet se mencionan los siguientes parámetros relacionados con la velocidad de conmutación:
Tiempo de retardo (Delay Time, td)
Tiempo de subida (Rise time, tr)
Tiempo de almacenamiento (Storage time, ts)
Tiempo de caída (Fall time, tf)

He encontrado una página que explica el significado de estos conceptos
http://www.uv.es/marinjl/electro/transistores.html#3

A mí no me basta para aclararme, pero está claro que los tiros van por ese lado.