Espruino:Примеры/Измерение и управление скоростью вентилятора: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
Нет описания правки
 
(не показана 1 промежуточная версия этого же участника)
Строка 46: Строка 46:
Во-первых, нам надо сохранить в переменные названия контактов, чтобы нам было легче к ним обращаться. Если вы используете какие-то другие контакты, то их нужно задать именно здесь:
Во-первых, нам надо сохранить в переменные названия контактов, чтобы нам было легче к ним обращаться. Если вы используете какие-то другие контакты, то их нужно задать именно здесь:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var FAN_SPEED_OUT = B8;
var FAN_SPEED_OUT = B8;
var FAN_SPEED_IN = B9;
var FAN_SPEED_IN = B9;
Строка 53: Строка 53:
Теперь давайте быстренько проверим, всё ли работает нормально:
Теперь давайте быстренько проверим, всё ли работает нормально:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
setWatch(function (e) {  
setWatch(function (e) {  
   digitalWrite(LED1, e.state);  
   digitalWrite(LED1, e.state);  
Строка 63: Строка 63:
В результате светодиод будет то включаться, то выключаться, а если вентилятор замедлится, светодиод будет включаться и выключаться ещё медленнее.
В результате светодиод будет то включаться, то выключаться, а если вентилятор замедлится, светодиод будет включаться и выключаться ещё медленнее.


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
digitalWrite(FAN_SPEED_OUT, 0);
digitalWrite(FAN_SPEED_OUT, 0);
</syntaxhighlight>
</syntaxhighlight>
Строка 69: Строка 69:
Теперь вентилятор (и [[светодиод]]) должны работать очень медленно.
Теперь вентилятор (и [[светодиод]]) должны работать очень медленно.


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
digitalWrite(FAN_SPEED_OUT, 1);
digitalWrite(FAN_SPEED_OUT, 1);
</syntaxhighlight>
</syntaxhighlight>
Строка 77: Строка 77:
Давайте удалим прерывание (что прекратит мигание [[светодиод]]а) и попробуем кое-что новенькое.
Давайте удалим прерывание (что прекратит мигание [[светодиод]]а) и попробуем кое-что новенькое.


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
clearWatch()
clearWatch()
</syntaxhighlight>
</syntaxhighlight>
Строка 83: Строка 83:
Ниже – функция, измеряющая время между сигналами от вентилятора. С её помощью мы рассчитаем количество оборотов вентилятора в минуту (переменная [[RPM]]).
Ниже – функция, измеряющая время между сигналами от вентилятора. С её помощью мы рассчитаем количество оборотов вентилятора в минуту (переменная [[RPM]]).


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
function onFanMovement(e) {  
function onFanMovement(e) {  
   var d = e.time-lastTime;
   var d = e.time-lastTime;
Строка 96: Строка 96:
В коде выше мы рассчитываем количество оборотов в минуту (переменная [[RPM]]), а в одной минуте, как известно, 60 секунд. Кроме того, на каждый оборот приходится по 2 импульса, так что нам нужно удвоить продолжительность импульса, чтобы измерить его. В итоге получаем вот такую формулу:
В коде выше мы рассчитываем количество оборотов в минуту (переменная [[RPM]]), а в одной минуте, как известно, 60 секунд. Кроме того, на каждый оборот приходится по 2 импульса, так что нам нужно удвоить продолжительность импульса, чтобы измерить его. В итоге получаем вот такую формулу:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
RPM = 60 / (d*2);
RPM = 60 / (d*2);
</syntaxhighlight>
</syntaxhighlight>
Строка 104: Строка 104:
Поэтому просто напечатайте:
Поэтому просто напечатайте:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
RPM
RPM
</syntaxhighlight>
</syntaxhighlight>
Строка 112: Строка 112:
Теперь давайте замедлим вентилятор:
Теперь давайте замедлим вентилятор:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
digitalWrite(FAN_SPEED_OUT, 0);
digitalWrite(FAN_SPEED_OUT, 0);
</syntaxhighlight>
</syntaxhighlight>
Строка 118: Строка 118:
А потом снова узнаем количество оборотов в минуту. Оно должно уменьшиться.
А потом снова узнаем количество оборотов в минуту. Оно должно уменьшиться.


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
RPM
RPM
</syntaxhighlight>
</syntaxhighlight>
Строка 126: Строка 126:
Для этого мы можем отредактировать функцию '''onFanMovement()''', чтобы включать и выключать вентилятор в зависимости от нужной нам скорости. Мы также будем включать и выключать [[светодиод]], чтобы видеть, что происходит:
Для этого мы можем отредактировать функцию '''onFanMovement()''', чтобы включать и выключать вентилятор в зависимости от нужной нам скорости. Мы также будем включать и выключать [[светодиод]], чтобы видеть, что происходит:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var targetRPM = 200;
var targetRPM = 200;
function onFanMovement(e) {  
function onFanMovement(e) {  
Строка 140: Строка 140:
Теперь мы можем задать в переменной '''targetRPM''' нужное нам количество оборотов в минуту, а [[Espruino]] воспользуется им для изменения скорости вращения вентилятора (вы увидите это по светодиоду).
Теперь мы можем задать в переменной '''targetRPM''' нужное нам количество оборотов в минуту, а [[Espruino]] воспользуется им для изменения скорости вращения вентилятора (вы увидите это по светодиоду).


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var targetRPM = 300;
var targetRPM = 300;
</syntaxhighlight>
</syntaxhighlight>
Строка 150: Строка 150:
Вместо использования переменной '''fanOn''' (с помощью которой задаётся либо включение, либо выключение вентилятора) мы создадим и запомним новую переменную. В ней будет храниться значение ''между «0» и «1»'', определяющее то, с какой силой работает вентилятор. Вместо того, чтобы просто задавать его, мы будем увеличивать и уменьшать его на маленькое значение в зависимости от того, быстрее ли или медленнее ли нужного нам значения крутится вентилятор.
Вместо использования переменной '''fanOn''' (с помощью которой задаётся либо включение, либо выключение вентилятора) мы создадим и запомним новую переменную. В ней будет храниться значение ''между «0» и «1»'', определяющее то, с какой силой работает вентилятор. Вместо того, чтобы просто задавать его, мы будем увеличивать и уменьшать его на маленькое значение в зависимости от того, быстрее ли или медленнее ли нужного нам значения крутится вентилятор.


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
var fanDrive = 0.5;
var fanDrive = 0.5;
function onFanMovement(e) {  
function onFanMovement(e) {  
Строка 170: Строка 170:
Если вы попробуете задать значение '''targetRPM''' сейчас, вентилятор достигнет нужной скорости вращения за несколько секунд. Чтобы узнать, какое именно значение было задано для вентилятора, напечатайте следующее:
Если вы попробуете задать значение '''targetRPM''' сейчас, вентилятор достигнет нужной скорости вращения за несколько секунд. Чтобы узнать, какое именно значение было задано для вентилятора, напечатайте следующее:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
fanDrive
fanDrive
</syntaxhighlight>
</syntaxhighlight>
Строка 178: Строка 178:
Теперь давайте попробуем резко увеличить скорость вращения вентилятора и посмотрим, что получится!
Теперь давайте попробуем резко увеличить скорость вращения вентилятора и посмотрим, что получится!


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
fanDrive=1;
fanDrive=1;
</syntaxhighlight>
</syntaxhighlight>
Строка 190: Строка 190:
Во-первых, мы больше не будем менять скорость вентилятора при изменении сигнала от вентилятора. Мы будем делать это 10 раз в секунду независимо от его текущей скорости:
Во-первых, мы больше не будем менять скорость вентилятора при изменении сигнала от вентилятора. Мы будем делать это 10 раз в секунду независимо от его текущей скорости:


<syntaxhighlight lang="javascript" enclose="div">
<syntaxhighlight lang="javascript">
function onFanMovement(e) {  
function onFanMovement(e) {  
   var d = e.time-lastTime;
   var d = e.time-lastTime;
Строка 214: Строка 214:
=См.также=
=См.также=


{{ads}}
 


=Внешние ссылки=
=Внешние ссылки=
Строка 220: Строка 220:
<references />
<references />


{{Навигационная таблица/Espruino}}
{{Навигационная таблица/Портал/Espruino}}
{{Навигационная таблица/Телепорт}}

Текущая версия от 15:06, 20 мая 2023

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Измерение и управление скоростью вентилятора[1]

Это руководство подразумевает, что вы уже умеете загружать код на Espruino. Если вы этого делать не умеете, пройдите сначала вот это руководство.

Введение

В этом руководстве мы измерим скорость вращения 4-проводного CPU-вентилятора Intel, а потом сами зададим ему скорость вращения. Измерения будут делаться при помощи функции setWatch() – с её помощью мы зададим прерывание на нужном контакте, в результате чего при изменении состояния этого контакта будет запущена нужная нам функция.

Ниже – видеоверсия этого руководства:

Control Fan Speed with Espruino JavaScript for ARM Microcontrollers

Подсоединение

4-проводные вентиляторы Intel – это 12-вольтовые вентиляторы, совместимые с более ранними 2- и 3-проводными моделями. Они оснащены одним цифровым вводом для управления скоростью и одним цифровым выводом для её измерения. Его контакты отвечают за следующее:

Контакт вентилятора Цвет провода За что отвечает
1 Чёрный Земля
2 Жёлтый 12-вольтовое питание
3 Зелёный Датчик для измерения скорости, притянутый к «0» (притягивается дважды за оборот)
4 Синий Управление скоростью

Хотя в таблице выше написано, что вентилятору нужно 12 вольт (и это на 100% верно), но мы в целях упрощения это проигнорируем и вместо 12 вольт будем питать вентилятор от 5 вольт – именно столько Espruino получает через USB-соединение.

Итак:

  • Подключите чёрный (1) провод к контакту GND на плате Espruino.
  • Подключите жёлтый (2) провод к 5 вольтам на плате Espruino.
  • Подключите зелёный (3) провод к любому свободному контакту на плате Espruino (я в этом примере решил воспользоваться B9).
  • Подключите синий (4) провод к любому аналоговому контакту, умеющему генерировать ШИМ. Чтобы узнать, какие контакты умеют это делать, напечатайте analogWrite(), но если рядом с контактом говорится DAC, не используйте его. Я для этого примера решил воспользоваться контактом B8.
  • Наконец, найдите резистор на 10 кОм, а затем подключите одну его ножку к зелёному (3) проводу вентилятора, а другую – к 3.3 вольтам на плате Espruino. Это притянет датчик скорости к значению «1». Если вам лень это делать, просто подключите 2 и 3 провода вентилятора друг к другу при помощи резистора.
  • После включения питания вентилятор должен начать вращаться (но медленно – потому что по-хорошему его нужно питать от 12 вольт).

Код

Во-первых, нам надо сохранить в переменные названия контактов, чтобы нам было легче к ним обращаться. Если вы используете какие-то другие контакты, то их нужно задать именно здесь:

var FAN_SPEED_OUT = B8;
var FAN_SPEED_IN = B9;

Теперь давайте быстренько проверим, всё ли работает нормально:

setWatch(function (e) { 
  digitalWrite(LED1, e.state); 
}, FAN_SPEED_IN, { repeat: true });

Это заставит светодиод моргнуть после того, как индикатор скорости вентилятора отправит сигнал. При каждом изменении сигнала этот код будет вызывать функцию, задающую светодиоду новое состояние, которое было прислано в сигнале.

В результате светодиод будет то включаться, то выключаться, а если вентилятор замедлится, светодиод будет включаться и выключаться ещё медленнее.

digitalWrite(FAN_SPEED_OUT, 0);

Теперь вентилятор (и светодиод) должны работать очень медленно.

digitalWrite(FAN_SPEED_OUT, 1);

Теперь вентилятор (и светодиод) снова должны начать работать быстро.

Давайте удалим прерывание (что прекратит мигание светодиода) и попробуем кое-что новенькое.

clearWatch()

Ниже – функция, измеряющая время между сигналами от вентилятора. С её помощью мы рассчитаем количество оборотов вентилятора в минуту (переменная RPM).

function onFanMovement(e) { 
  var d = e.time-lastTime;
  lastTime = e.time;  
  RPM = 60 / (d*2);
}
setWatch(onFanMovement, FAN_SPEED_IN, { repeat: true, edge: 'falling' });

Обратите внимание, что в свойстве edge задано значение falling. Это нужно, чтобы наша функция вызывалась, только если состояние сигнала сменится с «1» на «0» (т.е. «упадёт»). Дело в том, что сигналы могут быть несимметричными (то есть переключение с «1» на «0» и с «0» на «1» занимает разное время). Но мы замеряем только «падение» сигнала, и поэтому нам об этой проблеме беспокоиться не нужно.

В коде выше мы рассчитываем количество оборотов в минуту (переменная RPM), а в одной минуте, как известно, 60 секунд. Кроме того, на каждый оборот приходится по 2 импульса, так что нам нужно удвоить продолжительность импульса, чтобы измерить его. В итоге получаем вот такую формулу:

RPM = 60 / (d*2);

Итак, загрузите функцию onFanMovement(e), показанную выше, на Espruino. После её загрузки ничего не произойдёт, потому что Espruino будет просто в фоновом режиме обновлять переменную RPM.

Поэтому просто напечатайте:

RPM

В результате в консоли будет напечатано количество оборотов в минуту.

Теперь давайте замедлим вентилятор:

digitalWrite(FAN_SPEED_OUT, 0);

А потом снова узнаем количество оборотов в минуту. Оно должно уменьшиться.

RPM

А что если нам нужно сделать значение в переменной RPM постоянным?

Для этого мы можем отредактировать функцию onFanMovement(), чтобы включать и выключать вентилятор в зависимости от нужной нам скорости. Мы также будем включать и выключать светодиод, чтобы видеть, что происходит:

var targetRPM = 200;
function onFanMovement(e) { 
  var d = e.time-lastTime;
  lastTime = e.time;
  RPM = 60 / (d*2);
  var fanOn = RPM < targetRPM;
  digitalWrite(LED1, fanOn);
  digitalWrite(FAN_SPEED_OUT, fanOn);
}

Теперь мы можем задать в переменной targetRPM нужное нам количество оборотов в минуту, а Espruino воспользуется им для изменения скорости вращения вентилятора (вы увидите это по светодиоду).

var targetRPM = 300;

Если задать здесь слишком большое значение (например, 10000), вентилятор никогда не разовьёт такую скорость, а светодиод останется включенным. А если задать слишком низкое значение, светодиод останется выключенным.

Обратите внимание, что если задать значение где-то посередине, скорость вращения будет постоянно колебаться. Исправить это можно при помощи использования широтно-импульсной модуляции – с её помощью мы будем очень быстро менять скорость вращения вентилятора.

Вместо использования переменной fanOn (с помощью которой задаётся либо включение, либо выключение вентилятора) мы создадим и запомним новую переменную. В ней будет храниться значение между «0» и «1», определяющее то, с какой силой работает вентилятор. Вместо того, чтобы просто задавать его, мы будем увеличивать и уменьшать его на маленькое значение в зависимости от того, быстрее ли или медленнее ли нужного нам значения крутится вентилятор.

var fanDrive = 0.5;
function onFanMovement(e) { 
  var d = e.time-lastTime;
  lastTime = e.time;
  RPM = 60 / (d*2);
  if (RPM < targetRPM) {
    if (fanDrive<1) fanDrive += 0.01;
  } else {
    if (fanDrive>0) fanDrive -= 0.01;
  }
  digitalWrite(LED1, fanDrive>0.5);
  analogWrite(FAN_SPEED_OUT, fanDrive);
}

Но значение в переменной fanDrive не должно выходить за пределы диапазона 0-1. Если задать в targetRPM какое-то недостижимое число, значение в fanDrive будет постоянно увеличиваться, а когда вы снова решите задать в targetRPM значение поменьше, у Espruino уйдёт бездна времени на то, чтобы снова сделать значение в fanDrive меньше «1».

Если вы попробуете задать значение targetRPM сейчас, вентилятор достигнет нужной скорости вращения за несколько секунд. Чтобы узнать, какое именно значение было задано для вентилятора, напечатайте следующее:

fanDrive

Если вы будете какое-то время вызывать эту переменную, то увидите, что её значение постоянно меняется, чтобы достичь значения, заданного в targetRPM.

Теперь давайте попробуем резко увеличить скорость вращения вентилятора и посмотрим, что получится!

fanDrive=1;

В результате вентилятор закрутится с максимальной скоростью, а затем Espruino начнёт потихоньку её замедлять, пока не достигнет нужного значения.

Итак, теперь наша система работает гораздо лучше, но подстройка скорости будет происходить дольше, если вентилятор крутится медленнее нужной скорости. Если вентилятор остановится, то скорость не подстроится вообще.

Это решается очень просто!

Во-первых, мы больше не будем менять скорость вентилятора при изменении сигнала от вентилятора. Мы будем делать это 10 раз в секунду независимо от его текущей скорости:

function onFanMovement(e) { 
  var d = e.time-lastTime;
  lastTime = e.time;
  RPM = 60 / (d*2);
}
function onTimer() {
  if (RPM < targetRPM) {
    if (fanDrive<1) fanDrive += 0.01;
  } else {
    if (fanDrive>0) fanDrive -= 0.01;
  }
  digitalWrite(LED1, fanDrive>0.5);
  analogWrite(FAN_SPEED_OUT, fanDrive);
}
setInterval(onTimer, 100);

Итак, теперь вентилятор будет подстраивать скорость вращения одинаково – независимо от того, медленнее нужной скорости он крутится или быстрее. Кроме того, нужная скорость будет гарантированно достигнута в течение не более 10 секунд.

Есть другие способы управления устройствами, с помощью которых нужной скорости можно достичь гораздо быстрее... Например, рекомендуем ознакомиться с этой статьёй о ПИД-регуляторах на «Википедии».

См.также

Внешние ссылки