16 LED на PCA9685 с Adafruit_PWMServoDriver

Jasur
Jasur аватар
Offline
Зарегистрирован: 05.01.2018

Всем привет, нужна помощь с кодом под шилд PCA9685.
Сделал на arduino uno волнообразную мигалку c шим из 6 светодиодных лент, интенсивность которых зависит от ультрозвукового датчика HY-SRF05:

#include <Ultrasonic.h>

Ultrasonic ultrasonic1(12, 13);
Ultrasonic ultrasonic2(A2, A1);
const byte ledPins[6] = {3,5,6,9,10,11};

void setup() {
    pinMode( ledPins, OUTPUT );
}

void loop() {  
    delay(100);
    int rotation1 = ultrasonic1.distanceRead();
    int rotation2 = ultrasonic2.distanceRead();
    rotation1 = constrain(rotation1,0,300);
    rotation2 = constrain(rotation2,0,300);
    int dim1 = map(rotation1,0,300,1,50);
    int dim2 = map(rotation2,0,300,1,50);
    if (rotation1 = 0) dim1 = 300;
    if (rotation2 = 0) dim2 = 300;
    int tot = dim1+dim2;
    int step;
    if (tot < 3 || tot > 50) step = 1;
    if (tot < 50 && tot > 30) step = 2;
    if (tot < 30 && tot > 10) step = 3;
    if (tot < 10 && tot > 5) step = 4;
    if (tot < 5) step = 5;
    
    for(int i=0; i<3; i=i+step){
        analogWrite(ledPins[0], i);
        analogWrite(ledPins[1], i);
        analogWrite(ledPins[2], i);
        analogWrite(ledPins[3], i);
        analogWrite(ledPins[4], i);
        analogWrite(ledPins[5], i);
        delay(1);
    }    
    for(int i=255; i>=0; i=i-step){
        analogWrite( ledPins[0], (255-i)/dim1 );
        analogWrite( ledPins[3], (255-i)/dim2 );
        delay(1);
    }
    for(int i=255; i>=0; i=i-step){
        analogWrite( ledPins[0], i/dim1 );
        analogWrite( ledPins[3], i/dim2 );
        analogWrite( ledPins[1], (255-i)/dim1 );
        analogWrite( ledPins[4], (255-i)/dim2 );
        delay(1);
    }
    for(int i=255; i>=0; i=i-step){
        analogWrite( ledPins[1], i/dim1 );
        analogWrite( ledPins[4], i/dim2 );
        analogWrite( ledPins[2], (255-i)/dim1 );
        analogWrite( ledPins[5], (255-i)/dim2 );
        delay(1);
    }
    for(int i=255; i>=0; i=i-step){
        analogWrite( ledPins[2], i/dim1 );
        analogWrite( ledPins[5], i/dim2 );
        delay(1);
    }    
}

 

Решив расширить шим с помощью PCA9685 столкнулся с проблемой адаптации кода. 
чекнул примеры шим из библиотеки "Adafruit_PWMServoDriver.h":


void setup() {
  Serial.begin(9600);
  Serial.println("16 channel PWM test!");

  pwm.begin();
  pwm.setPWMFreq(1600);  // This is the maximum PWM frequency

  // if you want to really speed stuff up, you can go into 'fast 400khz I2C' mode
  // some i2c devices dont like this so much so if you're sharing the bus, watch
  // out for this!
  Wire.setClock(400000);
}

void loop() {
  // Drive each PWM in a 'wave'
  for (uint16_t i=0; i<4096; i += 8) {
    for (uint8_t pwmnum=0; pwmnum < 16; pwmnum++) {
      pwm.setPWM(pwmnum, 0, (i + (4096/16)*pwmnum) % 4096 );
    }
#ifdef ESP8266
    yield();  // take a breather, required for ESP8266
#endif
  }
}

все ленты одновременно плавно гаснут по циклу, но когда изменяю значение pwmnum на нужный мне выход на плате, домпустим 1 или 3, реакции никакой, либо все ленты горят в половину.

Адптировал свой код под эту плату:


#include <Ultrasonic.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Ultrasonic ultrasonic1(12, 13);
Ultrasonic ultrasonic2(A2, A1);
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

void setup() {
  Serial.begin(9600);
  Serial.println();
    pwm.begin();
    pwm.setPWMFreq(1600);
  Wire.setClock(400000);
}

void loop() {    
    delay(1);
    int rotation1 = ultrasonic1.distanceRead();
    int rotation2 = ultrasonic2.distanceRead();
    rotation1 = constrain(rotation1,0,300);
    rotation2 = constrain(rotation2,0,300);
    int dim1 = map(rotation1,0,300,1,800);
    int dim2 = map(rotation2,0,300,1,800);
    if (rotation1 = 0) dim1 = 4096;
    if (rotation2 = 0) dim2 = 4096;
    int tot = dim1+dim2;
    int step;
    if (tot < 3 || tot > 50) step = 16;
    if (tot < 50 && tot > 30) step = 32;
    if (tot < 30 && tot > 10) step = 48;
    if (tot < 10 && tot > 5) step = 64;
    if (tot < 5) step = 80;
    
    for(int i=0; i<4096; i=i+step){
        pwm.setPWM(0, 0, i);
        pwm.setPWM(1, 0, i);
        pwm.setPWM(2, 0, i);
        pwm.setPWM(3, 0, i);
        pwm.setPWM(4, 0, i);
        pwm.setPWM(5, 0, i);
        delay(1);
    }    
    for(int i=4096; i>=0; i=i-step){
        pwm.setPWM(0, 0, (4096-i)/dim1);
        pwm.setPWM(3, 0, (4096-i)/dim2);
        delay(1);
    }
    for(int i=4096; i>=0; i=i-step){
        pwm.setPWM(0, 0, i/dim1);
        pwm.setPWM(3, 0, i/dim2);
        pwm.setPWM(1, 0, (4096-i)/dim1);
        pwm.setPWM(4, 0, (4096-i)/dim2);
        delay(1);
    }
    for(int i=4096; i>=0; i=i-step){
        pwm.setPWM(1, 0, i/dim1);
        pwm.setPWM(4, 0, i/dim2);
        pwm.setPWM(2, 0, (4096-i)/dim1);
        pwm.setPWM(5, 0, (4096-i)/dim2);
        delay(1);
    }
    for(int i=4096; i>=0; i=i-step){
        pwm.setPWM(2, 0, i/dim1);
        pwm.setPWM(5, 0, i/dim2);
        delay(1);
    } 
    yield();   
}

но вместо волнообразного последовательного переливания света от одной ленты к другой все ленты одновременно плавно загораются и резко гаснут. Не понимаю в чём ошибка и что я делаю не так.
 

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Возможно я ошибаюсь, но в Вашей программе я не увидел адреса шилда PCA9685. Соответственно команды посылаются куда то.

Jasur
Jasur аватар
Offline
Зарегистрирован: 05.01.2018

Видимо адреса прописаны в библиотеке, но подключаю согласно со всеми примерами использования этой библиотеки с этим шилдом SCL - "A5"; SDA - "A4" ни в одном примеме программ не прописаны адреса амого шилда. Пробовал так же подключать на порты arduino  "SDA" и "SCL" реакция та же. 

b707
Offline
Зарегистрирован: 26.05.2017

Jasur пишет:

Видимо адреса прописаны в библиотеке, но подключаю согласно со всеми примерами использования этой библиотеки с этим шилдом SCL - "A5"; SDA - "A4"

возможно, в библиотеке забит какой-то адрес, но вероятно он не совпадает с реальным адресом Вашего шилда. Судя по описанию, у этого шилда не фиксированный адрес, а может выбираться из диапазона 0x40-0x7F. Вам нужно запустить сканер и определить адрес шилда. а потом либо поправить его в библиотеке (если он там жестко прописан) - либо прописать иннициализации.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

b707 пишет:

возможно, в библиотеке забит какой-то адрес, но вероятно он не совпадает с реальным адресом Вашего шилда. Судя по описанию, у этого шилда не фиксированный адрес, а может выбираться из диапазона 0x40-0x7F. Вам нужно запустить сканер и определить адрес шилда. а потом либо поправить его в библиотеке (если он там жестко прописан) - либо прописать иннициализации.

У этого шилда адрес должен задаваться перемычками (перепайками) на плате.

Jasur
Jasur аватар
Offline
Зарегистрирован: 05.01.2018

В коде прописано:

 

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

пустые скобки соответствуют адресу по умолчанию 0х40, что соответствует адресу шилда без запаеных перемычек.

Сканер подтвердил выдав устройство с адресом 0х40

Проблема была аппаратная, всё дело в питании. Почему-то когда запитал шилд отдельно (не от ардуино) всё стало работать и каждый из 16 каналов действуют. Но проблема с кодом осталось. Вместо плавного угосания светодиоды резко выключаются.

Jasur
Jasur аватар
Offline
Зарегистрирован: 05.01.2018

Переписал код. Проблема решена. Всем спасибо за поддержку)