Giuseppe Parrello

 

Embedded Ventola PWM


Introduzione

Questo progetto si basa su una ventola PWM a 4 pin, per i test ho usato una ventola Noctua NF-A14 PWM, alimentata a 12 volt - l'alimentazione deve essere fornita tramite un alimentatore esterno. Andremo a gestire questa ventola in modo tale da poterla accendere/spegnere o per variare la sua velocità. Per semplicità andremo ad usare la scheda di sviluppo FTDI FT232H (di cui esiste una pagina dedicata su questo sito) e la scheda di sviluppo NXP PCA9685 (di cui esiste una pagina dedicata su questo sito).
Questo progetto si divide in due parti, la seconda parte è semplicemente una variante della prima e comprende due interruttori che vengono usati per variare la velocità della ventola.

 

Progetto 1 - Collegamento

La ventola deve essere parzialmente collegata alla scheda di sviluppo NXP PCA9685. I connettori di collegamento sono elencati qui di seguito:

Immagine Scheda FT232H Scheda PCA9685 Ventola

FT232H - PCA9685 - PWM FAN

AD0 SCL ------
AD1 + AD2 SDA ------
+5V VCC ------
GND GND ------
------ Canale 0 - PWM Segnale PWM
------ ------ Segnale RPM (non usato)
------ ------ VCC (alimentatore)
------ ------ GND (alimentatore)

 

Progetto 1 - Codice Python

Per usare questo progetto, è richiesta la presenza della libreria "PyFTDI". Il codice Python è il seguente:

import time
import pca9685_ftdi

"""
  Blue   = PWM signal
  Green  = RPM speed signal
  Yellow = +VCC
  Black  = GND
"""

# Create library object using our FTDI I2C port
pwm = pca9685_ftdi.PCA9685_FTDI()

MIN       = 300
STEP      = 5
SLEEP     = 0.025
CHANNEL   = 0

try:
    while True:
        print("\nFAN off")
        pwm.setPWM(CHANNEL, 0, 0)
        time.sleep(10)
 
        print("\nFAN full speed")
        pwm.setPWM(CHANNEL, 0, 4095)
        time.sleep(10)

        print("\nIncreasing FAN speed")
        for fadeValue in range(MIN, 4096, STEP):
            pwm.setPWM(CHANNEL, 0, fadeValue)
            time.sleep(SLEEP)

        print("\nDecreasing FAN speed")
        for fadeValue in range(4095, MIN - STEP, -STEP):
            pwm.setPWM(CHANNEL, 0, fadeValue)
            time.sleep(SLEEP)

        time.sleep(2)

except KeyboardInterrupt:
    # Capture keyboard ^C to exit the program
    print('\nYou terminated the program. The program ends!')
    #pwm.clearAllPins()
    pwm.set_all_pwm(0, 0)
    pwm.close()

 

Progetto 2 - Collegamento

La ventola deve essere parzialmente collegata alla scheda di sviluppo NXP PCA9685, mentre i due interruttori devono essere collegati alla scheda di sviluppo FTDI FT232H. I connettori di collegamento sono elencati qui di seguito:

Immagine Scheda FT232H Scheda PCA9685 Ventola Interruttore 1 Interruttore 2

FT232H - PCA9685 - PWM FAN - SWITCHES

AD0 SCL ------ ------ ------
AD1 + AD2 SDA ------ ------ ------
+3.3V VCC ------ ------ ------
GND GND ------ ------ ------
------ Canale 0 - PWM Segnale PWM ------ ------
------ ------ Segnale RPM (non usato) ------ ------
------ ------ VCC (alimentatore) ------ ------
------ ------ GND (alimentatore) ------ ------
+5V ------ ------ Pin 1 Pin 1
AD3 ------ ------ Pin 2 ------
AD4 ------ ------ ------ Pin 2

 

Progetto 2 - Codice Python

Per usare questo progetto, è richiesta la presenza della libreria "PyFTDI". Il codice Python è il seguente:

import time
import pca9685_ftdi

"""
  Blue   = PWM signal
  Green  = RPM speed signal
  Yellow = +VCC
  Black  = GND
"""

GPIO_IN_OFFSET = 3  # FT232H GPIO inputs are AD3-AD4 (AD0-AD2 are reserved to I2C)

MIN          = 0
MAX          = 4096
STEP         = 256
SLEEP        = 0.25
CURRENTVALUE = MIN
CHANNEL      = 0

# Create library object using our FTDI I2C port
pwm = pca9685_ftdi.PCA9685_FTDI()
pwm._i2c.set_retry_count(16)
gpio = pwm._i2c.get_gpio()
# We set the two GPIO pins to write mode as we need to set them to 0 before reading the values
# (otherwise, if we set them to read mode, the values will be always 1).
gpio.set_direction(0b11000, 0b11000)
gpio.write(0b000000)
pwm.setPWM(CHANNEL, 0, 0)
print(CURRENTVALUE)

try:
    while True:
        din = (gpio.read(True) >> GPIO_IN_OFFSET) & 0b11
        if (din == 1 or din == 2):
           if (din == 1):
              CURRENTVALUE = CURRENTVALUE + STEP
           if (din == 2):
              CURRENTVALUE = CURRENTVALUE - STEP
           if (CURRENTVALUE < MIN):
              CURRENTVALUE = MAX
           if (CURRENTVALUE > MAX):
              CURRENTVALUE = MIN
           print(CURRENTVALUE)
           pwm.setPWM(CHANNEL, 0, CURRENTVALUE)
           time.sleep(SLEEP)

except KeyboardInterrupt:
    # Capture keyboard ^C to exit the program
    print('\nYou terminated the program. The program ends!')
    #pwm.clearAllPins()
    pwm.set_all_pwm(0, 0)
    pwm.close()