Site icon AranaCorp

Usar um módulo PCA9685 com o Arduino

0
(0)

O módulo PCA9685 é um controlador de 16 canais que permite controlar 16 saídas PWM através de comunicação I2C. Seu uso libera entradas e saídas do seu microcontrolador, possibilitando conduzir até 16 LEDs ou servomotores (ou qualquer outro módulo que tome um sinal PWM como entrada) usando dois pinos (SCL e SDA). Com isso, os pinos do seu microcontrolador ficam livres para outros módulos, como sensores.

Pré-requisito: Conduzir um servomotor com o Arduino

Material

Princípio de funcionamento

O módulo é baseado no controlador PCA9685, que controla saídas PWM usando comunicação I2C e um relógio integrado. Este módulo comporta 6 pontes que permitem selecionar o endereço da placa e colocar, no mesmo barramento, até 62 controladores, para um total de 992 servomotores (endereços disponíveis de 0x40 a 0x7F).
Ele permite acionar saídas PWM com uma frequência ajustável e uma resolução de 12 bits. O módulo é compatível com microcontroladores de 5V e 3,3V.

Esquema

O módulo é equipado com um barramento I2C e uma entrada de energia. O barramento I2C se conecta da seguinte forma:

Neste tutorial, usamos a placa Arduino UNO, mas ele pode ser adaptado a outros microcontroladores. Basta adaptar os pinos I2C disponíveis no microcontrolador em questão e, possivelmente, o código.

Código

Para utilizar o módulo PCA9685, usamos a biblioteca Adafruit_PWMServoDriver.h. As larguras de PWM são geralmente dadas em microssegundos por um período de 20ms (50Hz), mas estes valores podem mudar conforme o fornecedor e o servomotor utilizado. Nesse caso, é preciso modificar os valores do código para adaptá-los ao seu servomotor.
Aqui, utilizamos o servomotor MG90S, cujos gamas são de 400-2400µs por 20ms.

Para definir o comando PWM, a biblioteca apresenta duas funções: setPWM() e writeMicroseconds(). A função writeMicroseconds() permite utilizar diretamente os valores do construtor. Para a função setPWM, precisamos encontrar a largura de pulso correspondente em 4096 (2^12, 12bits).

Exemplo: A frequência é de 50Hz, logo um período de 20ms ou 20000µs.
pwmvalmin=400/20000*4096=81.92-> 90 arredondando com uma margem de segurança
pwmvalmax=2400/20000*4096=491.52 -> 480 arredondando com uma margem de segurança
Isso nos dá as seguintes equivalências:
pca.writeMicroseconds(i,400) equivale a pca.setPwm(i,0,90)
pca.writeMicroseconds(i,2400) equivale a pca.setPwm(i,0,480)
Utilize a função que melhor lhe convier.

//Libraries
#include <Wire.h>//https://www.arduino.cc/en/reference/wire
#include <Adafruit_PWMServoDriver.h>//https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library

//Constants
#define nbPCAServo 16

//Parameters
int MIN_IMP [nbPCAServo] ={500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500};
int MAX_IMP [nbPCAServo] ={2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500, 2500};
int MIN_ANG [nbPCAServo] ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int MAX_ANG [nbPCAServo] ={180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180};

//Objects
Adafruit_PWMServoDriver pca= Adafruit_PWMServoDriver(0x40);

void setup(){
//Init Serial USB
Serial.begin(9600);
Serial.println(F("Initialize System"));
pca.begin();
pca.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
}

void loop(){
  pcaScenario();
}

void pcaScenario(){/* function pcaScenario */ 
////Scenario to test servomotors controlled by PCA9685 I2C Module
for (int i=0; i<nbPCAServo; i++) {
  Serial.print("Servo");
  Serial.println(i);
      //int middleVal=((MAX_IMP[i]+MIN_IMP[i])/2)/20000*4096; // conversion µs to pwmval
      //pca.setPWM(i,0,middleVal);
      for(int pos=(MAX_IMP[i]+MIN_IMP[i])/2;pos<MAX_IMP[i];pos+=10){
        pca.writeMicroseconds(i,pos);delay(10);
      }
      for(int pos=MAX_IMP[i];pos>MIN_IMP[i];pos-=10){
        pca.writeMicroseconds(i,pos);delay(10);
      }
      for(int pos=MIN_IMP[i];pos<(MAX_IMP[i]+MIN_IMP[i])/2;pos+=10){
        pca.writeMicroseconds(i,pos);delay(10);
      }
      pca.setPin(i,0,true); // deactivate pin i
    }
}

int jointToImp(double x,int i){/* function jointToImp */ 
////Convert joint angle into pwm command value
     
      int imp=(x - MIN_ANG[i]) * (MAX_IMP[i]-MIN_IMP[i]) / (MAX_ANG[i]-MIN_ANG[i]) + MIN_IMP[i];
      imp=max(imp,MIN_IMP[i]);
      imp=min(imp,MAX_IMP[i]);
      
 return imp;
}

Aplicações

Fontes

Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Exit mobile version