Непонятное поведение куллера: управление по ШИМ
- Войдите на сайт для отправки комментариев
Доброго дня!
Уже третий день ломаю голову над непонятным поведением кулера, управляемого шилдом от 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"); }; //если нужен толчек, то перезапустить функцию через секунду }
Помогите разобраться, пожалуйста!
у вас кулер с двумя проводами, тремя или четырьмя? Только кулер с четырься проводами обязан правильно работать от ШИМ, причем ШИМ ему нужно подавать на соотвествующтй провод. Все остальные на ШИМ правильно реагировать не обязаны, хотя как правило и работвют нормально
я бы в вашем случае сначала проверил адекватность реагирования кулера на ШИМ как таковой. Можно взять крутилку, прицепить ее на аналоговый вход и написать скетч для ручного регулирования от нуля до 255 с выводом значения в сериал. Таким образом можно найти диапазон устойчивой и предсказуемой работы
Кулер с 2мя проводами, подключаю к выводу DCMOTOR на Motor шилде, где впринципе и идет управление двигателями по 2м проводам...
Пробовал гонять по стандартному примеру из библиотеки AFMotor: разгон от 0 до 255 и обратно, а также работа на одной скорости:
запускается на 40-80 (если не помогать), в обратную сторону крутится до 30. Работает стабильно без колебаний.
А вот 3х проводной работает хуже - запускается только на максимуме и останавливается на 80... но он хитрый: если его остановить, то он стоит пару секунд, а потом сам трогается, типа защиты от заклинивания, видимо из-за этого..
Но причина нестабильности судя по всему в скетче либо же аппаратная какая-то вылазит на этом скетче.
А еще, встречаются бесщеточные моторы, в которых, внутри стоит своя электроника. Вот они то совсем не обязаны работать он ШИМ.)))
ПЫСЫ: как раз поведение их похоже на поведение вентилятора ТС.
Блин, походу оказалось все куда прозаичнее... Прересобрал схему еще раз, на это раз запустил все с подключением шилда напрямую (посадкой на дуину) - все заработало четко.
Видимо при подключении шилда монтажными проводками был неуверенный контакт на каких-то пинах, и так вот чудно выходило, что если задавать в цикле 0>>255 или constant speed то все работало, а если рулить в динамике, начинались глюки... Так что извиняюсь за беспокойство.
Но вот беда: этот шилд перекрывает все пины, тогда как мне нужно только 2 мотора из 4х (и еще двух серв), так что куча свободных пинов остается перекрытой - распаивать шилд нехотелось бы... как бы выкрутится?
Блин, походу оказалось все куда прозаичнее... Прересобрал схему еще раз, на это раз запустил все с подключением шилда напрямую (посадкой на дуину) - все заработало четко.
Видимо при подключении шилда монтажными проводками был неуверенный контакт на каких-то пинах, и так вот чудно выходило, что если задавать в цикле 0>>255 или constant speed то все работало, а если рулить в динамике, начинались глюки... Так что извиняюсь за беспокойство.
Но вот беда: этот шилд перекрывает все пины, тогда как мне нужно только 2 мотора из 4х (и еще двух серв), так что куча свободных пинов остается перекрытой - распаивать шилд нехотелось бы... как бы выкрутится?
вы когда проводами соединяли то как питание на шилд подавали? От источника питания напрямую или от ардуино? Рекомендую подать отдельно от источника и плюс и минус, т.е. Провода питания от ардуино и шилда тянуть отдельно и соединять у источника питания. Не должны токи питания вентилятора проходить через ардуину. Ну и контакты проверьте. В крайнем случае нужные несколько проводов можно запаять на ардуине и шилде
А еще, встречаются бесщеточные моторы, в которых, внутри стоит своя электроника. Вот они то совсем не обязаны работать он ШИМ.)))
ПЫСЫ: как раз поведение их похоже на поведение вентилятора ТС.
они по моему все такие
я обычно делаю не прямой шим, а ставлю LC фильтр где C несколько сотен мкф. Получается управление не Шим, а напряжением. Хотя обычно и с ШИМ работает. Но врядли так же стабильно, ведь получается электроника внутри вентилятора сотни раз в секунду перезапускается при работе от прямого шим
Arduino UNO работает от импульсного БП на 9V, подключенного через штекер питания ардуины. + USB кабель к ноуту для мониторинга Serial порта.
А на шилд подается напряжение на клеммы внешнего питания от импульсного БП на 12V. Перемычка джампера снята, т.е. питание должно быть раздельным.
Дело либо в дребезге контактов (т.к. использовал для соединения по два провода на пин: (мама-мама и папа-папа) либо в использовании для управления движком M1 и M2 каких-то незадокументированных пинов, кроме 3,4,7,8,11,12 и GND. Попробую пропаять их, либо установить поверх шилда гребенки, чтобы можно было подключаться к пинам.
Расскажите пожалуйста про управление напряжением чуть подробнее, т.к. это много лучше! А то в схемотехнике я ноль, сам бы не сообразил: я правильно понял, что на вывод от шилда к двигателю, нужно паралельно поставить кондер на несколько сотен мкф?, а в качестве индуктивности (L) что выступает, обмотка самого движка?
Индуктивность в виде отдельной детали, 100-200мкгн расчитанные на ток вентилятора
надо уточнить что там у вас на выходе шилда. Для таких дел я никакие шилды не использую, использую просто транзистор, индуктивность, диод и конденсатор.
вот схема то что под рукой то что я публиковал. Справа на листе кусочек с транзистором Q3 - это оно. P10 вход ШИМ, P7 - сюда подключается вентилятор. Паралельно конденсаторутхорошо еще подключить диод в обоатном включении типа 1n5819/1n5822
http://radiokot.ru/articles/54/05.png