Непонятное поведение куллера: управление по ШИМ

Draghkon
Offline
Зарегистрирован: 17.09.2013

Доброго дня!

Уже третий день ломаю голову над непонятным поведением кулера, управляемого шилдом от adafruit и библиотекой AF_Motor.

Задача: управлять оборотами двух (пробовал с одним - то же самое) компьютерных кулеров по температуре с датчика ds18b20.

Алгоритм должен работать так:

Если температура больше 32С - увеличивать обороты на 5% от заданного максимума, до максимальных.

Если меньше - понижать по той же схеме.

Если обороты ниже порога в 80, то дать толчек максимум оборотов на 1сек. (иначе кулер может не стартануть).

 

Проблема в том, что кулер ведет себе непредсказуемо: обороты то затихают, то увеличиваются, при этом показания Serial (для отладки) вроде сответствуют ожидаемым.... 

Вот используемый скетч:

#include <AFMotor.h>
#include <SimpleTimer.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#define ONE_WIRE_BUS 2

AF_DCMotor fan1(1,MOTOR12_2KHZ); //куллеры обдува на порту 1
AF_DCMotor fan2(2,MOTOR12_2KHZ);
AF_DCMotor fanMotor[2]{fan1, fan2};// массив кулеров
OneWire oneWire(ONE_WIRE_BUS); //иниц. 1 wire
DallasTemperature sensors(&oneWire);// init d18b20
int fanSpeed[2]; //массив значений скоростей
float temp; //тек. темп
byte maxFanSpeed[2]; //массив макс. скоростей
SimpleTimer timer; //таймер, millis вместо delay

void setup() {
  Serial.begin(115200);
 
for (byte i = 0; i < 2; i++){
    fanMotor[i].setSpeed(0); //init fans
    fanMotor[i].run(RELEASE);
  };
  sensors.begin();
  fanSpeed[0]=80; //начальная скорость
  fanSpeed[1]=80;

  timer.setInterval(3000,Temp); //проверять температуру раз в 3 сек
  maxFanSpeed[0]=220; //макс значения скоростей
  maxFanSpeed[1]=180;
}

void loop() {
  timer.run(); 

  for (int i=0; i<2;i++){
    fanMotor[i].run(FORWARD); 
  };
}

void Temp()
{
  static float lastTemp = 22; //предыдущее значение темпы
  sensors.requestTemperatures(); // Send the command to get temperatures
  temp = sensors.getTempCByIndex(0); //текущая температура ds18b20
  Serial.print("DS temp: "); 
  Serial.print(temp);
  Serial.print("      ");
  Serial.print("Last temp: ");
  Serial.println(lastTemp);
  lastTemp=temp; 
  if (temp <= -127){ temp = lastTemp; }; //error defense
  if (temp >= 45){ // если темп. критическая - выключить все
    Serial.println("CRITICAL");}
  else if (temp < 45 && temp<lastTemp) { //если температура меньше критической,  и падает то включить обратно
   Serial.println("FINE AGAINE");}
  
for (byte i = 0; i < 2; i++){ //перебор кулеров
  if (temp >= 32){ // если больше 32 увеличиваем обороты
    float Step=(float(maxFanSpeed[i]) / 100)*5;
    Serial.print("step:");
    Serial.println(Step);
    fanSpeed[i] += int(Step);
  } else if (temp < 32 && (temp-lastTemp)>0.3) { // если меньше и падает уменьшаем
     float Step=(float(maxFanSpeed[i]) / 100)*5;
    Serial.print("step:");
    Serial.println(Step);
    fanSpeed[i] -= int(Step);
  };
  if (fanSpeed[i] >= maxFanSpeed[i]){ fanSpeed[i] = maxFanSpeed[i]; } //но не более максимальной
    else if (fanSpeed[i] <= 80){ fanSpeed[i] = 80; }; //но не менее минимальной
  
  Serial.print("fanspeed of fan ");
      Serial.print(i);
      Serial.print("  : ");
      Serial.print(fanSpeed[i]);
  Serial.println();
  };

  SetSpeed();
}
void SetSpeed()
{

static byte prev[2] = { 0, 0 }; // last fanspeed
  static boolean st = 0; // флаг толчка
  Serial.print("st:");
  Serial.println(st);
  
  for (byte i = 0; i < 2; i++){
      
        fanMotor[i].setSpeed(fanSpeed[i]);
        Serial.print(" NEW FAN SPEED of fan ");
        Serial.print(i);
        Serial.print(" is: ");
        Serial.print(fanSpeed[i]);
        Serial.print("      ");
        Serial.print(" Prev fan speed is:");
        Serial.print(prev[i]);
        Serial.println();
     
        st = 0; //возвращаем флаг в 0
        if (fanSpeed[i] <= 80 && prev[i] != fanSpeed[i]){//если скорость ниже зупускной   и это новое значение - дать толчек 
        if (!st){ // если его не было
          fanMotor[i].setSpeed(255);
          fanMotor[i].run(FORWARD); //пуск кулера
          Serial.print(" PUSH fan ");
          Serial.print(i);
          Serial.print("      ");
          st = 1;
          Serial.println();
        };
      };
         prev[i] = fanSpeed[i]; //новое предыдущее значение
      };
      
  if (st){ timer.setTimeout(2000, SetSpeed); Serial.println("push timer is on"); }; //если нужен толчек, то перезапустить функцию через секунду
  
}

  

Помогите разобраться, пожалуйста!

 

axill
Offline
Зарегистрирован: 05.09.2011

у вас кулер с двумя проводами, тремя или четырьмя? Только кулер с четырься проводами обязан правильно работать от ШИМ, причем ШИМ ему нужно подавать на соотвествующтй провод. Все остальные на ШИМ правильно реагировать не обязаны, хотя как правило и работвют нормально

я бы в вашем случае сначала проверил адекватность реагирования кулера на ШИМ как таковой. Можно взять крутилку, прицепить ее на аналоговый вход и написать скетч для ручного регулирования от нуля до 255 с выводом значения в сериал. Таким образом можно найти диапазон устойчивой и предсказуемой работы

Draghkon
Offline
Зарегистрирован: 17.09.2013

Кулер с 2мя проводами, подключаю к выводу DCMOTOR на Motor шилде, где впринципе и идет управление двигателями по 2м проводам... 

Пробовал гонять по стандартному примеру из библиотеки AFMotor: разгон от 0 до 255 и обратно, а также работа на одной скорости:

запускается на 40-80 (если не помогать), в обратную сторону крутится до 30. Работает стабильно без колебаний.

А вот 3х проводной работает хуже - запускается только на максимуме и останавливается на 80... но он хитрый: если его остановить, то он стоит пару секунд, а потом сам трогается, типа защиты от заклинивания, видимо из-за этого..

Но причина нестабильности судя по всему в скетче либо же аппаратная какая-то вылазит на этом скетче.

keefa
Offline
Зарегистрирован: 19.06.2015

А еще, встречаются бесщеточные моторы, в которых, внутри стоит своя электроника. Вот они то совсем не обязаны работать он ШИМ.)))

ПЫСЫ: как раз поведение их похоже на поведение вентилятора ТС.

 

Draghkon
Offline
Зарегистрирован: 17.09.2013

Блин, походу оказалось все куда прозаичнее...  Прересобрал схему еще раз, на это раз запустил все с подключением шилда напрямую (посадкой на дуину) - все заработало четко.

Видимо при подключении шилда монтажными проводками был неуверенный контакт на каких-то пинах, и так вот чудно выходило, что если задавать в цикле 0>>255 или constant speed то все работало, а если рулить в динамике, начинались глюки...  Так что извиняюсь за беспокойство.

Но вот беда: этот шилд перекрывает все пины, тогда как мне нужно только 2 мотора из 4х (и еще двух серв), так что куча свободных пинов остается перекрытой - распаивать шилд нехотелось бы...  как бы выкрутится?

axill
Offline
Зарегистрирован: 05.09.2011

Draghkon пишет:

Блин, походу оказалось все куда прозаичнее...  Прересобрал схему еще раз, на это раз запустил все с подключением шилда напрямую (посадкой на дуину) - все заработало четко.

Видимо при подключении шилда монтажными проводками был неуверенный контакт на каких-то пинах, и так вот чудно выходило, что если задавать в цикле 0>>255 или constant speed то все работало, а если рулить в динамике, начинались глюки...  Так что извиняюсь за беспокойство.

Но вот беда: этот шилд перекрывает все пины, тогда как мне нужно только 2 мотора из 4х (и еще двух серв), так что куча свободных пинов остается перекрытой - распаивать шилд нехотелось бы...  как бы выкрутится?

вы когда проводами соединяли то как питание на шилд подавали? От источника питания напрямую или от ардуино? Рекомендую подать отдельно от источника и плюс и минус, т.е. Провода питания от ардуино и шилда тянуть отдельно и соединять у источника питания. Не должны токи питания вентилятора проходить через ардуину. Ну и контакты проверьте. В крайнем случае нужные несколько проводов можно запаять на ардуине и шилде

axill
Offline
Зарегистрирован: 05.09.2011

keefa пишет:

А еще, встречаются бесщеточные моторы, в которых, внутри стоит своя электроника. Вот они то совсем не обязаны работать он ШИМ.)))

ПЫСЫ: как раз поведение их похоже на поведение вентилятора ТС.

 

они по моему все такие

я обычно делаю не прямой шим, а ставлю LC фильтр где C несколько сотен мкф. Получается управление не Шим, а напряжением. Хотя обычно и с ШИМ работает. Но врядли так же стабильно, ведь получается электроника внутри вентилятора сотни раз в секунду перезапускается при работе от прямого шим

Draghkon
Offline
Зарегистрирован: 17.09.2013

Arduino UNO работает от импульсного БП на 9V, подключенного через штекер питания ардуины. + USB кабель к ноуту для мониторинга Serial порта. 

А на шилд подается напряжение на клеммы внешнего питания от импульсного БП на 12V. Перемычка джампера снята, т.е. питание должно быть раздельным.

Дело либо в дребезге контактов (т.к. использовал для соединения по два провода на пин: (мама-мама и папа-папа) либо в использовании для управления движком M1 и M2 каких-то незадокументированных пинов, кроме 3,4,7,8,11,12 и GND.  Попробую пропаять их, либо установить поверх шилда гребенки, чтобы можно было подключаться к пинам.

Расскажите пожалуйста про управление напряжением чуть подробнее, т.к. это много лучше! А то в схемотехнике я ноль, сам бы не сообразил: я правильно понял, что на вывод от шилда к двигателю, нужно паралельно поставить кондер на несколько сотен мкф?, а в качестве индуктивности (L) что выступает, обмотка самого движка?

axill
Offline
Зарегистрирован: 05.09.2011

Индуктивность в виде отдельной детали, 100-200мкгн расчитанные на ток вентилятора

надо уточнить что там у вас на выходе шилда. Для таких дел я никакие шилды не использую, использую просто транзистор, индуктивность, диод и конденсатор.

вот схема то что под рукой то что я публиковал. Справа на листе кусочек с транзистором Q3 - это оно. P10 вход ШИМ, P7 - сюда подключается вентилятор. Паралельно конденсаторутхорошо еще подключить диод в обоатном включении типа 1n5819/1n5822

http://radiokot.ru/articles/54/05.png