Espruino:Примеры/Симуляция физики воды с помощью серводвигателей

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин (Cubewriter) Контакты:</br>* Skype: cubewriter</br>* E-mail: cubewriter@gmail.com</br>* Максим Кузьмин на freelance.ru
Проверка/Оформление/Редактирование: Мякишев Е.А.


Симуляция физики воды с помощью серводвигателей[1]

Espruino - Water Simulation

Это очень простая симуляция метода конечных элементов. Анализ с помощью метода конечных элементов применяется во многих областях – например, чтобы рассчитать воздушный поток вокруг корпуса болида «Формулы-1» или то, в состоянии ли мост себя поддерживать.

Основной принцип этого метода очень прост – возьмите что-либо и поделите на некоторое количество частей, а затем рассчитайте, как будет функционировать каждая из этих частей.

В этой статье мы создадим (очень примерную) симуляцию воды, текущей по тонкому каналу. Мы поделим воду на несколько вертикальных столбцов, каждый из которых будет наделён некоторой «массой», а также будет стараться коснуться других столбцов, находящихся слева и справа. Вот и всё. Это очень примитивная симуляция, но с её помощью можно создать вполне реалистичный эффект водной ряби (который, к слову, используется во многих компьютерных играх).

Нам понадобятся

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

Просто подключите шесть серводвигателей к контактам B13, B14, B15, C4, C5 и C6. Более подробно о подключении серводвигателей к плате читайте в этой статье.

Код

Просто скопируйте код ниже в правую часть Web IDE, а затем кликните на кнопку загрузки кода.

// Оставляем свободные места в начале и конце
// для стационарных точек, которым не нужны серводвигатели:
var servos = [undefined,B13,B14,B15,C4,C5,C6,undefined];
// Стартовая позиция для каждой точки:
var pos = new Float32Array(servos.length);
// Скорость вращения каждой точки:
var velocity = new Float32Array(servos.length);

// Эта функция будет вызываться очень часто
// для выполнения каждого шага симуляции:
// of the simulation
function step() {
  var i;
  // Меняем позицию конечной точки при нажатии на кнопку:
  pos[0] = digitalRead(BTN) ? 0.5 : 0;
  // Для каждой точки...
  for (i=1;i<servos.length-1;i++) {
    // Ускорение зависит от дистанции между 
    // этой точкой и её соседями: 
    var accel = ((pos[i-1]+pos[i+1])/2) - pos[i];
    // Рассчитываем новую скорость 
    // (с учётом трения и ускорения):
    velocity[i] = velocity[i]*0.95 + accel*0.1;
  }
  // И, наконец, для каждой точки...
  for (i=1;i<servos.length-1;i++) {
    // ...рассчитываем новую позицию:
    pos[i] += velocity[i];
    // Отправляем новую позицию серводвигателю:
    var p = 1.5+E.clip(pos[i],-0.5,0.5);
    digitalPulse(servos[i],1,p);
  }
}

// Вызываем это 50 раз в секунду:
setInterval(step, 20);

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

См.также

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