3 заметки с тегом

TMP36

Световой терменвокс.

18 марта 2013, 13:07

А теперь мы немного помузицируем. С помощью фоторезистора и пьезоэлемента мы будем делать световой терменвокс. Терменвокс — это музыкальный инструмент, издающий звуки, в зависимости от движений, которые производит музыкант вокруг инструмента. Такие звуки часто используют в фильмах ужасов.

У терменвокса две антенны, при изменении положения рук исполнителя относительно них  изменяется ёмкость колебательного контура антенн. Эти антенны подключены к аналоговой схеме, которая создает звук. Одна антенна отвечает за частоту звука, а вторая за его громкость. Arduino, конечно же, не может воспроизвести загадочные звуки этого инструмента, но можно эмулировать их с помощью функции tone(). На рисунках ниже можно увидеть разницу между модуляциями произведёнными функцией analogWrite() и функцией tone(). Эти модуляции заставляют воспроизводящие устройства (такие как наушники, колонки или пьезоэлементы) издавать различые звуки.

Большую часть времени сигнал равен нулю, но частота такая же как и в ШИМ 150 PWM 50: analogWrite(50)
Большую часть времени сигнал равен единице, но частота такая же как и в ШИМ 50 PWM 150: analogWrite(50)
Рабочий цикл составляет 50% (половину времени сигнал есть, половину времени нет), но частота изменилась. TONE 440: tone(9,440)
Рабочий цикл такой же как и в Tone 440, но частота больше вдвое. TONE 880: tone(9,440)

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

Фоторезистор к Arduino мы подключим используя схему делителя напряжения. Ранее мы уже заметили, что когда считываем напряжение с этой схемы используя функцию analogRead(), получаемые значения не всегда полностью покрывают диапазон от 0 до 1023 (максимальный диапазон, который может быть считан с аналогового входа). Резистор фиксированного сопротивления, подсоединённый к «земле», ограничивает считываемые значения снизу, а максимальная яркость освещения — сверху. Вместо того, чтобы ограничивать диапазон возможных значений, можно откалибровать сенсор, получив максимальное и минимальное значения, и соотнести их с частотой извлекаемого звука с помощью функции map() (как мы уже делали), таким образом, диапазон частот, которые будет издавать наш терменвокс, станет максимально возможным. Так же к нашему сенсору добавится дополнительная «фича»: куда бы мы не перенесли схему, например, в более темное помещение, она будет автоматически подстраиваться.

Итак , вот схема, которую мы будем собирать:

Собранный макет:

Пишем программу, для управления терменвоксом:

int sVal;//Значение на фоторезисторе
int sLow=1023; //минимальное значение фоторезистора
int sHigh=0;//максимальное значение фоторезистора
int ledPin=13;//встроенный светодиод

void setup(){
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin,HIGH); //начало калибровки
  while(millis()<5000) { //калибруем в течении 5 секунд
    sVal=analogRead(A0);
    if (sVal>sHigh){
      sHigh=sVal;
    }
    if(sVal<sLow){
      sLow=sVal;
    }
  }
  digitalWrite(ledPin,LOW);//окончание калибровки
}

void loop(){
  int freq;
  sVal=analogRead(A0);//считываем значение с фоторезистора
  freq=map(sVal,sLow,sHigh,50,4000);//приводим значение
  tone(8,freq,20);//извлекаем звук
  delay(10);
}

Небольшой комментарий к программе:

Объявления переменных:

sVal — сюда будем считывать значение с фоторезистора;

sLow и sHigh — максимальное и минимальное значения, которые можно прочитать с фоторезистора. В начале программы они соответственно равны 1023 (минимальное) и 0 (максимальное). В процессе калибровки в этих переменных появятся реальные значения минимума и максимума.

ledPin — пин со светодиодом, при начале калибровки включим его, по окончании выключим.

Инициализация:

Включаем светодиод. Втечении первых пяти секунд, в цикле считывается значение с фоторезистора, если оно меньше уже зафиксированного минимального значения (первоначально 1023), то записываем его в минимальное, если оно больше уже зафиксированного максимального значения (первоначально 0), то записываем его в максимальное. Используем функцию mills(), для определения времени, прошедшего с момента включения Arduino.

Основная программа: вобщем довольно простая, функция tone() используется для воспроизведения звука, первый её параметр — пин, на который выводить звук, второй — частота звука, третий — длительность.

Вот что вышло:

Настоящий терменвокс позволяет управлять не только частотой звука, но и его громкостью. В этом примере мы можем менять только частоту. Если подсоединить потенциоментр последовательно с пьезоэлементом, то звук можно будет регулировать с помощью его ручки или можно поставить второй фоторезистор. Мы решили подключить потенциометр.

Схема и фото макета ниже, а вот видео:

Использование сервопривода.

10 марта 2013, 14:24

Сервопривод  — это такие типы двигателей, которые не крутятся все время по кругу, а поворачиваются на определённый угол и останавливаются до тех пор, пока им не поступит другая команда повернуться. Сервопривод обычно поворачиваются только на 180 градусов (половина круга). Если присоединить  к такому мотору вырезанную из картона шкалу, можно использовать его в качестве указателя чего-нибудь, например, настроения.

Аналогично тому, как мы использовали ШИМ для управления светодиодами в опыте с «лампой-хамелеоном», сервопривод ожидает поступления определенного количества импульсов, чтобы понять, на какой угол ему надо повернуться. С аналогового выхода Arduino импульсы всегда поступают через один и тот же временной интервал, но продолжительность их меняется от 1000 до 2000 микросекунд. Программу, которая генерирует такие импульсы написать не очень сложно самим, но среда разработки Arduino уже включает в себя специальную библиотеку для управления моторами. Поскольку сообщество разработчиков для Arduino достаточно велико, существует великое множество дополнительных программ и библиотек для разных сенсоров, актуаторов и прочих устройств, которые могут взаимодействовать с Arduino. И мы этим тоже будем пользоваться.

Схема, которую мы будем собирать выглядит так:

Один контакт потенциометр подсоединяем на плюс, второй — на минус, подвижный контакт  — к аналоговому входу Arduino. При вращении ручки потенциометр, напряжение между подвижным контактом (входом Arduino) и минусом будет изменяться, это изменение мы будем «читать» и управлять вращением сервопривод.

Сервопривод  тоже имеет три контакта: два — питание (плюс и минус), третий для управления, его подсоединяем с выходу Arduino.

Когда сервопривод начинает движение, ток, проходящий через него, значительно больше, чем во время самого движения, из-за этого происходить сильное падение напряжения во всей схеме. Если подключить два конденсатора параллельно сервопривод и потенциометр, можно это сгладить. Такие конденсаторы называют «развязывающие» или разделяющие, так как они отделяют изменения, произведенные какими-либо компонентами, от остальной схемы.

Итак, макет готов:

Теперь пишем программу:

#include<Servo.h> //используем библиотеку для управления сервоприводом
Servo motor;      //наш мотор
int potens=A0;    //пин потенциометра 
int motorpin=9;   //пин мотора
int potensVal=0;  //значение потенциометра
int angle;        //угол поворота сервопривода

void setup(){ 
  motor.attach(motorpin); //подключаем мотор
  Serial.begin(9600);
}

void loop(){
  potensVal=analogRead(potens);//читаем положение потенциометра
  Serial.print(«potensVal: „);
  Serial.print(potensVal);
  angle=map(potensVal,0,1023,0,179);//преобразуем в градусы
  Serial.print(“, angle: „);
  Serial.println(angle);
  motor.write(angle);//поворачиваем мотор
  delay(15);
}

Небольшой комментарий по преобразованию значения, считанного с потенциометр, в градусы. С аналогового входа Arduino можно считать значение от 0 до 1023, в зависимости от напряжения на нем. В случае с потенциометром мы задействует все эти значения. На аналоговый выход Arduino мы может подать значение от 0 до 254, а в случае с сервоприводом, в команду движения мы вообще можем передавать значения только до 179. То есть нам надо пропорционально преобразовать значения из интервала [0;1023] в интервал [0;179]. У Arduino для этого есть специальная функция map(), в качестве первого параметра мы передаем значение, которое надо преобразовать, в качестве второго и третьего — границы первого интервала, четвертое и пятое — границы второго  интервала. В результате функция возвращает преобразованное значение, которое уже можно использовать. После команды поворота добавлена небольшая пауза, чтобы сервопривод успел повернуться. Фу… вроде все.

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

Теперь мы решили вместо потенциометр поставить в схему термосенсор, и поворачивать сервопривод в зависимости от внешней температуры. Немного изменили программу:

void loop(){
  tempVal=analogRead(tempPin);
  float v=(tempVal/1024.0)*5.0;
  float t=(v-0.5)*100;
  Serial.print(» temperature: «);
  Serial.print(t);
  angle=map( t, 15, 35,0,179);
  Serial.print(«, angle: „);
  Serial.println(angle);
  motor.write(angle);
  delay(1000);
}

Преобразовываем значение, считанное с термосенсор, в градусы, как мы это уже делали. В функции map() мы указали интервал от 15 до 35, потому что именно в этих пределах будет меняться температура в нашем опыте, и сервопривод будет поворачиваться на все 180 градусов при изменении температуры.

angle

Heat-o-Meter (измерение температуры).

25 февраля 2013, 18:26

Arduino можно использовать для измерения температуры.
Переключатели и кнопки — замечательно, но реальный мир вокруг не всегда можно описать двумя состояниями (вкл. и выкл.)

Немного теории:

Несмотря на то, что Arduino  — это цифровое устройство, оно может получать информацию с аналоговых сенсоров для измерения температуры или освещенности. Для этих целей необходимо использовать встроенный в Arduino аналого-цифровой перобразователь (АЦП). Аналоговые входы A0-A5 выдают значение от 0 до 1023, что соответствует напряжению от 0 до 5-ти вольт.

Для измерения температуры мы использовали температурный сенсор (TMP 36).

Термосенсор (TMP36)

Этот компонент изменяет напряжение на выходе в зависимости от температуры окружающей среды. Датчик имеет три контакта: один подсоединяется на «ground», второй  — на «power», а третий, который выдает изменяющееся напряжение, подсоединяется к Arduino. В программе для этого проекта мы будем считывать значения, которые выдает сенсор, и использовать их для включения и выключения светодиодов для индикации температуры.

Теперь к практике. Как обычно, сначала рисуем «схему»:

В собранном виде на макетной плате, она выглядит так:

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

Вот такая получилась программа, для считывания и вывода информации с сенсора:

int spin = A0; //датчик температуры
void setup(){
  Serial.begin (9600);//для вывода на экран компьютера
}
void loop(){
  int sVal = analogRead(spin);//Считываем информацию с сенсора
  Serial.print(«Sensor Value: „);//выводим значение на экран компьютера
  Serial.print(sVal);
  //конвертируем значение в вольты
  float v=(sVal/1024.0)*5.0;
  Serial.print(“, Volts: „);
  Serial.print(v);
  Serial.print(“, degrees C: „);
  //переводим вольты в градусы
  float t=(v-0.5)*100;
  Serial.println(t);
}

В этой программе использована команда Serial.begin(9600), с помощью неё открывается соединение между Arduino и компьютером. Функция analogRead() считывает значение с аналогового входа и возвращается значение от 0 до 1024, в зависимости от напряжения. Функция Serial.print() отправляет информацию с Arduino на компьютер, затем эта информация отображается в терминале.

Как расчитывается температура? Сначала необходимо понять сколько вольт получается на выходе термосенсора. Поскольку всего может быть 1024 значения (от 0 до 1023), а напряжение от 0В до 5В, используется формула [значение на аналоговом входе]* 5В/1024. Затем по документации на этот термосенсор переводим выдаваемое им напряжение в градусы по шкале Цельсия t=(v-0.5)*100.

Вот как выглядят результаты работы программы:

Теперь программируем работу светодиодов. Базовой температурой будем считать 23 градуса (такая температура была у нас в комнате). Если термосенсор нагревается на 2 градуса — загорается первый диод, еще на 2 (всего на 4) — второй диод, затем еще на 4 градуса (всего на 8) — третий диод.

Параллельно а работой над программой мы решили, что будет интереснее сделать светодиоды разноцветными:

Макет с разноцветными диодами

Вот наша программа:

int spin = A0; //датчик температуры
float basetemp= 23.0; //комнатная температура
int led1 = 2;//красный
int led2 = 3;//жёлтый
int led3 = 4;//зелёный

void setup(){
  Serial.begin (9600);//для вывода на экран компьютера
  pinMode(led1,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(led3,OUTPUT);
  digitalWrite(led1,LOW);
  digitalWrite(led2,LOW);
  digitalWrite(led3,LOW);
}

void loop(){
  int sVal = analogRead(spin);
  Serial.print(«Sensor Value: „);//выводим информацию на экран компьютера
  Serial.print(sVal);
  //конвертируем значение в вольты
  float v=(sVal/1024.0)*5.0;
  Serial.print(“, Volts: „);
  Serial.print(v);
  Serial.print(“, degrees C: „);
  //переводим вольты в градусы
  float t=(v-0.5)*100;
  Serial.println(t);
  if(t<basetemp){//температура поднимается на 2 градуса — ничего не горит
    digitalWrite(led2,LOW);
    digitalWrite(led3,LOW);
    digitalWrite(led1,LOW);
  }
  else if( (t>=basetemp+2)&&(t<basetemp+4) ){//температура подниамется от 2 до 4 градусов горит только зеленый
    digitalWrite(led2,LOW);
    digitalWrite(led3,HIGH);
    digitalWrite(led1,LOW);
  }
  else if( (t>=basetemp+4)&&(t<basetemp+8) ){
    digitalWrite(led2,HIGH);
    digitalWrite(led3,LOW);
    digitalWrite(led1,LOW);
  }
  else if (t>=basetemp+8){
    digitalWrite(led2,LOW);
    digitalWrite(led3,LOW);
    digitalWrite(led1,HIGH);
  }
}

Результаты работы программы: