Простые мелодии для Arduino
- Войдите на сайт для отправки комментариев
Втр, 23/07/2019 - 21:24
Я хотел бы предложить Вашему вниманию программы
исполнения "биперной" музыки, которые я написал
в разное время. Это конечно не музыкальный шедевр
и даже не то, что было на Спектрумовском AY,
а просто интересные для начального обучения примеры
Архивы включают множество коротких мелодий.
С отключённым фильтром рекламы - сплошная реклама куда не ткни. Кликбейт како то.
Для того, чтобы примеры были «интересны для обучения», они должны быть хотя бы минимально грамотными. Давай посмотрим. Вот у тебя в комментарии написана важная вещь.
Ну, давай посмотрим, как мы её избежим. Активное сопротивление «обычного» динамика – 8Ω, плюс резистор 100Ω, таким образом имеем ток 5В/108Ω = 46,3мА. В то время как абсолютный максимум для пина ATmega328P – 40мА, т.е. мы превысили абсолютный максимум почти на 16%. Хорошо избежали!
Но это аппаратная часть. Посмотрим на программную.
Основа там, как я понимаю, вот эта функция:
// собственно аппаратный вывод звука // tone - полупериод импульса (микросекунды), а не частота звука // duration - длительность звука (миллисекунды) void playTone(int tone,int duration) { digitalWrite(LED,HIGH) for (unsigned long i=0;i < duration*1000L;i+=(tone*2)) { digitalWrite(SPEAKER,HIGH); delayMicroseconds(tone); digitalWrite(SPEAKER,LOW); delayMicroseconds(tone); } digitalWrite(LED,LOW) }Для чего ты смешиваешь в сравнении знаковые и беззнаковые величины (и плюёшь на соответствующее предупреждение компилятора) я не знаю, но Бог с ним, есть вещи поинтереснее.
Нигде в комментариях не сказано об ограничениях, потому, как я понимаю, я могу попытаться сыграть любую разумную ноту. Так? Хорошо, беру «ля» субконтроктавы (частота 27,5Гц, полупериод – 18182 микросекунды). Запускаю «playTone(18182, 2000);» – какая боль! Нихрена не играет и время 2 сек не выдерживает!
Может быть нельзя играть такие низкие звуки? Тогда нужно написать о существующем ограничении (не менее 30,53 Герц) в документации (комментариях). Но лучше всё же аккуратнее программировать и не допускать детских ошибок в своих программах, тогда и таких глупых ограничений не будет.
В общем, ты сначала пройди обучение сам, а потом уж будешь публиковать «примеры для обучения».
#define LED 13 #define SPEAKER 8 int f[]={16000,8000,4000,2000,1000,500,100,50,27}; void setup() { Serial.begin(9600); pinMode(LED,OUTPUT);pinMode(SPEAKER,OUTPUT); } void loop() {char i;int ton; for (i=0;i<9;i++) {ton=(int)(500000L/f[i]); Serial.print("tone() function f=");Serial.println(f[i]); tone(SPEAKER,f[i],500);delay(1000); //500+500 Serial.print("playTone() function f=");Serial.println(f[i]); playTone(ton,500);delay(500); } delay(2000); } //hardware play tone itself. tone is a delay in microseconds (not frequancy), //duration is a sound length in milliseconds void playTone(int tone,int duration) {digitalWrite(LED,HIGH); for (unsigned long i=0;i<duration*1000L;i+=(tone*2)) {digitalWrite(SPEAKER,HIGH); delayMicroseconds(tone); digitalWrite(SPEAKER,LOW); delayMicroseconds(tone); } digitalWrite(LED,LOW); }Активное сопротивление «обычного» динамика – 8Ω, плюс резистор 100Ω, таким образом имеем ток 5В/108Ω = 46,3мА. В то время как абсолютный максимум для пина ATmega328P – 40мА, т.е. мы превысили абсолютный максимум почти на 16%. Хорошо избежали!
Но это аппаратная часть.
Это еще не вся аппаратная часть. Даже из той весьма небольшой мощности, которую способен выдать вывод МК, на динамик мы пускаем менее 7.5%, остальные 92.5% попусту рассевивая на резисторе.
Посмотрим на программную.
Даже простые мелодии под Ардуино должен писать не программист, а музыкант. Но если человек не музыкант, то даже скачка продвинутого ПО не поможет.
Я вчера подготовил исправления, чтобы таки заработало, и уже почти выложил их, но передумал, решил дождаться реакции ТС и не зря. ТС оказался «всегда и во всём правым».
Знаешь, нормальные люди, когда допустят ошибку в программе, просто спокойно признают это и исправляют. И от этого их репутация ничуть не страдает. А тех же, кто упирается рогом «нет никакой ошибки – вы все тролли» просто макают в эти ошибки носом и над ними начинают смеяться. Ты решил пойти по этому пути. Отлично - это втой выбор свободного человека!
Итак, поехали:
Да, нет, проблема как раз в том, что именно программа не может выдать такую частоту из-за элементарной ошибки программиста. Давай оставим проблемы динамиков динамикам, а сами просто посмотрим на твою программу. Я утверждаю, что низкие ноты не играет именно она из-за детской ошибки, до динамиков даже дело не доходит - им не дают шанса. С твоего позволения я написал вот такой тест для упомянутй мною ноты «ля» субконтроктавы (частота 27,5Гц, полупериод – 18182 микросекунды). Проверь, надеюсь я аккуратно скопипастил и корректо внес дополнения для теста.
#define SPEAKER 13 // собственно аппаратный вывод звука // tone - полупериод импульса (микросекунды), а не частота звука // duration - длительность звука (миллисекунды) void playTone(int tone,int duration) { // digitalWrite(LED,HIGH); uint32_t playCounter = 0; for (unsigned long i=0;i < duration*1000L;i+=(tone*2)) { playCounter++; digitalWrite(SPEAKER,HIGH); delayMicroseconds(tone); digitalWrite(SPEAKER,LOW); delayMicroseconds(tone); } // digitalWrite(LED,LOW); Serial.print("playCounter: "); Serial.println(playCounter); } void setup(void) { Serial.begin(115200); pinMode(SPEAKER,OUTPUT); playTone(18182, 32000); }Программа должна напечатать количество прохождений цикла. И что же она печатает?
Т.е. эту ноту программа даже не попыталась сыграть! И динамик тут, ну совсем не приделах.
Кстати, если бы бы ты прислушался к предупреждения компилятора, то ошибку нашёл бы сразу, но он у тебя ...
Родной ты наш, открой диалог «Настройки» в IDE и найди там опцию «Сообщения компилятора». Если ты уберёшь «страусиное» умолчание «нет» и поставишь что-то более адекватное, то немедленно увидишь сообщение
Это «да», не только в Сети, но и в её окрестностях. Правда, с беграмотными аппаратными советами, направленными на угробление аппаратуры, и детскими ошибками в программе, а в остальном очень хорошая!
Был тут один Великий, у того тоже всегда было всё самое лучшее в сети :)
И да, кстати, о том «кому и зачем нужны такие ноты». А кому и зачем вообще нужна музыка? Ноты бывают от субконтроктавы до пятой октавы (и даже до седьмой в некоторых случаях). И это и есть музыка. Что же касается субконтроктавы непосредственно, так Тим Стромс её просто поёт. Но мы здесь говорим вовсе не о нужности или ненужности нот. Мы говорим о детских ошибках программирования в «учебных материалах» и об упирании рогом вместо того, чтобы просто сказать «ой, блин, лажанулся» и исправить.
Ноты бывают от субконтроктавы до пятой октавы (и даже до седьмой в некоторых случаях).
Я никогда про "дальше пятой" не слышал, а тут полез частоту подсмотреть для этого примера, а там словами описаны до пятой, а в таблице частот - до седьмой. Причём написано, что некая Джорджия Браун может петь аж до соль седьмой октавы.
Причём написано, что некая Джорджия Браун может петь аж до соль седьмой октавы.
у ней, наерна, карикатурное сапрано.
#define SPEAKER 8 // Это другая версия вывода звука, которая не испытывает трудностей с низкими частотами void toneWithDelay (uint8_t _pin, unsigned int frequency, unsigned long duration) { unsigned long TimeMs, TimeUs; unsigned int Micros; char PinValue; PinValue = 0; TimeMs = millis(); Micros = 500000L / frequency; while (!((millis() - TimeMs) >= duration)) { TimeUs = micros(); while (!((micros() - TimeUs) >= Micros)); PinValue = ~PinValue; if (frequency) digitalWrite(_pin, PinValue); } digitalWrite(_pin, 0); } // Доработанная программа для низких частот до 16 Hz // собственно аппаратный вывод звука // ton - полупериод импульса (микросекунды), а не частота звука // duration - длительность звука (миллисекунды) // ton <= 32766 (0x7FFE), что соответствует частоте 500000L/32766 около 16 Hz void playTone2(unsigned int ton,unsigned int duration) {unsigned int tondiv2=ton/2; for (unsigned long i=0;i<duration*1000L;i+=ton,i+=ton) {digitalWrite(SPEAKER,HIGH); //Аргумент delayMicroseconds не может быть больше 16383 (0x3FFF) // См DelayMicroseconds.html delayMicroseconds(tondiv2);delayMicroseconds(tondiv2); digitalWrite(SPEAKER,LOW); delayMicroseconds(tondiv2);delayMicroseconds(tondiv2); } } void setup(void) { Serial.begin(9600); pinMode(SPEAKER,OUTPUT); // Здесь первый аргумент - задержка полупериода мкс playTone2(18000, 2000);delay(1000); playTone2(25000, 2000);delay(1000); playTone2(32000, 2000);delay(1000); // Здесь первый аргумент - частота Hz toneWithDelay(SPEAKER,2000,2000);delay(1000); toneWithDelay(SPEAKER,20,2000);delay(1000); toneWithDelay(SPEAKER,18,2000);delay(1000); toneWithDelay(SPEAKER,8,2000); } void loop() {}Боюсь, что не случайно. Ваш пост #3 написан глумливо-издевательски. Не думаю, что у Ворот или ещё у кого-нибудь после такой отповеди возникнет желание снова смотреть Ваш код и пытаться помочь, если там есть проблемы (а они там, увы, есть, и не одна). А ведь Вам по сути привели конкретные условия при которых программа не работает. Что мешало посмотреть в чём дело, зачем было глумиться? Чрезмерная уверенность в собственной непогрешимости в "лучшести в сети"? Сами себе злобный буратино.
у ней, наерна, карикатурное сапрано.
Уж и не знаю, но 25 с копейками киголерц - ультразвук же голимый! Она не летучая мышь случаем? Может, просто зверька так зовут?
Я никогда про "дальше пятой" не слышал, а тут полез частоту подсмотреть для этого примера, а там словами описаны до пятой, а в таблице частот - до седьмой.
Мельком глянул - в статье и без этого достаточно ляпов.
PS. Хочешь, я прямо здесь опубликую таблицу с частотами "нот" до 12-й октавы включительно?
Зачем таблицу? Формула ж простая как грабли.
Зачем таблицу? Формула ж простая как грабли.
А я и не предлагал составлять таблицу на слух)))))))))))))))))
А чего до 12-ой, а не до 100500-ой? Компютеру не всё равно сколько считать?
100500 - это круто (как никак - частота от номера ноты зависит экспоненциально), боюсь, что текст такого объема перегрузит сервер, на котором крутится этот форум.