2016-12-21 15 views
0

Я играю с PIC 24, и в настоящее время у меня есть небольшая проблема с преобразованием герца в несколько секунд, а затем с его использованием в качестве задержки для отправки сигнала на пьезоэлемент (зуммер, зуммер, динамик и т. Д.), А я хотел бы заставить его играть определенные заметки.C - Hertz to Seconds и как получить подходящее время для задержки?

Я хочу знать, выполняю ли я свое преобразование с герца в секундах (мсек в коде), и если я правильно обрабатываю свой сигнал.

Вот код, где я беспокоили:

Мой герц до Int преобразования:

int16 note(int i) 
{ 
    float time = (1.0/i); 

    int fin = ((time/2) * 1000); 

    return fin; 
} 

и вот как я послать сигнал на PIC24 я использую:

void main() 
{ 
InitMCU(); 

output_high(PIN_D1); 
delay_ms(note(E)); 
output_low(PIN_D1); 
delay_ms(200); 
output_high(PIN_D1); 
delay_ms(note(E)); 
output_low(PIN_D1); 
delay_ms(200); 
} 

Вот как я определил ноты:

#define C 255 //do 
#define D 227 //re 
#define E 204 //mi 
#define F 191 
#define G 170 
#define A 153 
#define B 136 
#define C2 127 
+6

В чем проблема? Пожалуйста, добавьте вопрос – izlin

+0

_Hertz_ является единицей для частоты, а _second_ - единицей времени, поэтому название вопроса не имеет смысла. –

+0

Да В настоящее время я преобразовываю частотные единицы из герца во второй (период). Формула выглядит примерно так: T = 1/i и T/2 = delay/msec –

ответ

1

Прежде всего вы пытаетесь использовать квадратные волны для создания синусоидальных волн. Таким образом, это всегда будет звучать немного неправильно, если вы нацелитесь специально на целевую частоту с таймером. сделайте квадратную волну 440 Гц, она не «звучит» как синусоидальная волна 440 Гц. Может быть, физика обойдется, но я держу пари не так сильно, как ты хочешь.

Вы можете, если у вас есть скорость. Сделайте одно бит DAC с 90-х или когда это было. Если вы можете сделать ваши квадратные волны быстрее, чем динамик может физически двигаться, вы можете сказать, что посыпать больше, чем нули, на некоторое время говорят, что выталкивание динамика немного с контролируемой скоростью, а затем более нулей, чем в течение некоторого времени, дразнящего динамика. Динамик становится физическим фильтром низких частот. Вероятно, вы можете использовать PWM в микроконтроллере, чтобы помочь в этом. Но вам нужно динамически изменять его, и это PIC, поэтому у вас наверняка закончится нехватка ресурсов, прежде чем вы сможете кодировать множество таблиц для чистого звука.

Чтобы сделать квадратную волновую вещь, вам нужно изменить выходной контакт на половине частоты. Не выполняйте вычисления во время выполнения, затем сделайте это на своем калькуляторе или дайте инструментарию сделать это. Скажем, что вы используете процессор/таймер с частотой 1 МГц, и вы хотите 440 Гц на штыре. Вам нужен период в 1/440. hz - это циклы в секунду, поэтому инвертирование делает секунды за цикл. 0.00227272 (повторяется) секунд за цикл или период, поэтому вам нужно, чтобы он был высоким для половины и низким для половины (или наоборот, не имеет значения), поэтому , что означает 0,00113636 ... между изменениями выходного состояния.Если ваш таймер составлял 1 МГц, это 1/1 миллион секунд за цикл. Или одну микросекунду. сколько микросекунд в 0.00113636 ... 1136. Таким образом, каждый таймер 1136 указывает, что вы меняете состояние, вы читаете документы на таймере и подсчитываете его или увеличиваете или все, что подсчитано 1136 (обычно это цифры на основе нуля, поэтому 1135, а затем подсчитывают ноль, а затем флаг прерывания или состояния или что-то еще). вы также можете опросить счетчик, который подсчитывает/от всех из них до/от всех нулей и перекатывает, вычитает оттуда и замаскирует его количеством битов, которое подсчитывается, а разница - время. с 16-разрядным счетчиком (start-now) & 0xFFFF - разница, если требуемое время достаточно меньше 0xFFFF. 1136, несомненно, будет. подождите, пока не начнется минус (если это счетчик вниз или теперь запускается мин, если счетчик вверх).

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

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

https://en.wikipedia.org/wiki/1-bit_DAC

вы могли бы начать с треугольной волны делают сказать 66% рабочего цикла на 1/4 из 1136 микросекунд, скважность 33% 1/2 из 1136 микросекунд, тогда 66% для окончательного 1/4. Или один раз сделать 1/4, затем сделать 1/2 в одном рабочем цикле, а затем 1/2 в другом. Вы должны быть в состоянии найти или написать фильтр нижних частот, а не то, что вы знаете, что такое свойства динамиков, но вы можете почувствовать, как генерировать более медленную волну в пределах высшего. После треугольника вы можете попробовать трапецию. наращивайте с некоторой скоростью, сделайте 50% на бит, затем опуститесь, повторите в течение второй половины периода.

Для экспериментальных целей найдите или предварительно вычислите последовательность, охватывающую весь период, вы можете иметь код, который генерирует несколько сотен или тысяч строк кода, при этом вы можете быть справедливым, если не точно детерминированным X числом микросекунд может быть achived, выполнив точно Y количество инструкций или правильное сочетание инструкций Y как

on 
on 
off 
on 
off 
on 
on 
off 

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

Вы можете добавить простой R/C-фильтр, буквально два компонента, чтобы преобразовать поток бит в аналоговую форму сигнала, после чего вы подаете динамик или усиливаете, а затем подавайте динамик, здесь вы можете посмотреть на него область.

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

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

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

440Гц, как мы видели это 0.00113636 секунды в течение половины периода, так что будет 1millisecond на то миллисекунды прочь, ваш код должен сделать это

for(i=0;i<nperiods;i++) 
{ 
on 
delay_ms(1) 
off 
delay_ms(1) 
} 

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

Таким образом, существует ряд проблем с вышеперечисленным, прежде всего задержка в миллисекундах - это медленное замедление для того, что вы пытаетесь выполнить за микросекундную задержку, и вам нужно понять, сколько времени требуется для накладных расходов в цикле, наша математика показала 1136 микросекунд для 440 Гц с некоторой усеканием точности. но код, который делает задержку, esp на медленном mcu, как это, занимает много тактов, если это код C, а не asm, тогда многие другие, плюс код для включения и выключения gpio, вы должны вычесть/настройте их. Сфера применения поможет, если вы начнете с 1136, и область действия покажет период 3000us вместо 2272.7, тогда вам нужно вычесть это и повторить попытку. поэтому задержка 772 вместо 1136. Такого рода вещи.

Средний C - 261,6 Гц согласно Google, правый или неправильный позволяет работать с ним. то есть 3823 микросекунды. подавая вашу функцию примечания 255, которая, как я полагаю, является тем, что определяет, дает 1.9. Я принимаю миллисекунды. которая правильна до миллисекунд. который усекается до 1 миллисекунды или 2000 микросекунд, что составляет 500 Гц, что, конечно, далеко. что определение должно было быть 261 или 262 не 255 в любом случае правильным?

hmmm, так что вы пытаетесь сделать высокий импульс, но фиксированный длинный импульс 200 мс? поэтому, если вы накормили его записью E и предположили, что код не успел запуститься. она будет высокой в ​​течение 2 мс, то низкие за 200, и предполагая, что вы повторили, что это рабочий цикл 1% при частоте 1/201ms или 4,97 ... Гц, фортепианные частоты

https://en.wikipedia.org/wiki/Piano_key_frequencies

не показывайте примечание в 5hz. Я уверен, что он близок к некоторой гармонике, но довольно низко.

А будет иметь 3ms высоких 200 низкие частот или 1/203ms или 4,9 Гц

Другие, чем математика, делая среду выполнения с плавающей точкой на рисе (или в любом месте, что не делает иметь FPU) является чрезвычайно дорогостоящим, только математика, возможно, занимает больше времени, чем весь ваш цикл. абсолютно никакой причины для вычисления этого времени выполнения. вы могли бы легко сделать определения с помощью математики или использовать ваш калькулятор и сделали определения с жестко закодированными числами вручную. Он по-прежнему не работал бы с фиксированным низким периодом esp, который был бы настолько значительным по сравнению с нужными цифрами. с миллисекундной задержкой, предполагая, что код запускается мгновенно. на задержку 1 мс отсрочка 1 мс - 500 Гц. включение, задержка 2, выдержка 2, 250 Гц, задержка 3 равна 166, задержка 4 равна 125 и так далее. вы не собираетесь ударять по множеству реальных заметок, предполагая, что код запускается мгновенно, и что он не делает и использует миллисекундную задержку.

Чтобы сделать волну давления, вы хотите, чтобы динамик выходил из состояния покоя на половину цикла и всасывался обратно из состояния покоя на половину цикла, идеально в синусоидальном режиме, чтобы он медленно гаснул и возвращается, затем втягивается и гаснет. переход от состояния реселлера к выходу только будет работать уверенно, но вы все равно должны иметь рабочий цикл, чтобы приблизиться к квадратной волне. так что понимайте таймеры, которые у вас есть, с помощью pic вы можете легко скомпоновать некоторые циклы, которые записывают тактовые циклы, поскольку они детерминированы из того, что я помню. начните с частоты вашего процессора, что это? сколько процессорных циклов за один период вашей заметки? то же, что и выше с 440 Гц до 1 МГц. 0.0011363636 раз 1 миллион (секунды на половину периода времени тики в секунду, секунды отменяются, и вы получаете тики за половину периода работы математики на единицах точно так же, как цифры), если ваш mcu работает со скоростью 2 миллиона часов в секунду, то это 2 миллиона раз 0.001136363636 .. .

ТОГДА выясните, как включить его, подождите, когда количество часов процессора выключится и дождитесь этого количества часов процессора. напишите это в пьезо или другое и посмотрите, как это звучит.

Если вы имели 16 разрядные регистры, которые я держал пари, что вы не но, предполагая 1MHZ часы вы

load reg with some number 
top 
subtract reg,1 
compare with zero 
branch to top 

в сборке конечно. если предположить, что один такт для вычитания и сравнить каждый, а затем два для ветви, скажем, что это четыре за цикл, поэтому 1136/4 = 284. загружают регистр с предварительно вычисленным значением 284.

код стороны сбоку

top: 
gpio on 
load reg,284 
one: 
sub reg,1 
cmp reg,0 
bne one 
gpio off 
load reg,284 
two: 
sub reg,1 
cmp reg,0 
bne two 
jmp top 

Грубая, но это поможет вам начать путь.

Если у вас нет 16-разрядных регистров, но 8 бит, 1mhz 1136/0x100 = 4 остатка 112, который получился бы неплохим, если этот процессор занимает 4 такта за цикл, как я уже сделал, фантазировал выше. каждая задержка будет

mov reg,0xFF 
A: 
sub reg,1 
cmp reg,0 
bne A 
mov reg,28 
B: 
sub reg,1 
cmp reg,0 
bne B 

нет сомнений в том, бесчисленное количество ресурсов, здесь и в других местах описания задержки петли для членов семьи ПОС.

Вы могли бы просто крыло его и увидеть звуки изменить

#define DELX 300 
volatile unsigned int x; 
while(1) 
{ 
    output_high(PIN_D1); 
    for(x=0;x<DELX;x++) continue; 
    output_low(PIN_D1); 
    for(x=0;x<DELX;x++) continue; 
} 

и играть с разными номерами для определения. тон должен измениться, качество может быть не таким большим или, может быть, намного лучше, чем у вас сейчас, но оно должно измениться, если оно вообще слышно. есть вероятные утесы, которые вы ударите. Я предполагаю, что это 8-разрядный процессор, поэтому подсчет до 200 WAYY отличается от того, что подсчитывается до 300, это не будет частотой, которая в полтора раза ниже. возможно, он не будет линейным, может быть, зависит от компилятора, но это могут быть линейные сегменты с кинками здесь и там. 100-200 могут быть линейными и от 300 до 400, но от 200 до 300 не могут быть.

Это, вероятно, линейна, хотя

volatile unsigned int x; 
unsigned int y,z; 
for(z=0;z<1000;z++) 
for(y=0;y<100;y++) 
{ 
    output_high(PIN_D1); 
    for(x=0;x<z;x++) continue; 
    output_low(PIN_D1); 
    for(x=0;x<z;x++) continue; 
} 
2

Вам нужна петля!

repeat for note length: 
    on 
    delay 
    off 
    delay 

рассмотреть также расчета требуемого периода для каждой ноты офф-лайн и ввести его в виде целого числа, а не в Гц - процессор обыкновение быть тратить время в вычислениях с плавающей точкой

+0

Я исправляю его до бесконечного цикла, пока (1) {codehere}, однако динамик просто делает, ммм ... плоские звуки ... –

+0

Звучит немного как метроном, если я должен быть честным. –

+0

Потому что ваши задержки ошибочны. –

1

Середина примечание, как правило, 440 Гц. Если вы включаете и выключаете пьезодинамик 440 раз в секунду, задержка между последовательными переключениями составляет 1/880 секунды, что составляет 1,13636363636 мс. Это показывает две вещи:

  • Ваши расчеты удалены; и
  • Разрешение таймера одной миллисекунды слишком грубо для этого приложения.

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