Дверной звонок-ксилофон

payalnik08
Offline
Зарегистрирован: 16.12.2012

Доброе время суток всем самоделкиным. Есть большое желание сделать дверной звонок по принципу ксилофона на (ардуино) . Работой ксилофона будет управлять 8 или 16 эл.магнитов. Вот только не знаю какой контроллер выбрать и как управлять 16ю магнитами. Помогите люди добрые.

leshak
Offline
Зарегистрирован: 29.09.2011

Цитата:

Вот только не знаю какой контроллер выбрать

В принципе любой справится. 

Разница только "с каким удобней"

Лезете в описание плат - смотрите сколько у него выходов. Если вам хватает - можно брать. Если не хватает - брать либо с большим количеством ног, либо читать раздел документации на предмет "множим выходы ардуины с помощью сдвиговых регистров".

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

>

http://easyelectronics.ru/upravlenie-moshhnoj-nagruzkoj-postoyannogo-tok...

Все что написанно про реле - относится и к вашим магнитам (собственно реле это и есть ксилофон, щелкает только так. Просто язычек там "замыкает пластину", а не просто звук дает).

payalnik08
Offline
Зарегистрирован: 16.12.2012

Спасибо за ответ. Я думаю взять Arduino Uno , два сдвиговых регистра и развязать магниты транзисторными ключами либо как вы предлагаете реле с транзистором в одном корпусе.  

maksim
Offline
Зарегистрирован: 12.02.2012

Если электромагниты подойдут по току, то можно управлять ими ULN2803

payalnik08
Offline
Зарегистрирован: 16.12.2012

Спасибо за информацию она мне подойдет. 

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

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

payalnik08 пишет:

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

Основная проблема будет - идентифицировать звук, т.е. это Ваш звонок звонит, или шум (музыка) с улицы.

leshak
Offline
Зарегистрирован: 29.09.2011

payalnik08 пишет:

Спасибо за информацию она мне подойдет. 

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

Гиморойная.  Написать слово "распознавание" в тех-задании - легко. А реализовать в коде? Знаний (и математики в т.ч.) хватит что-бы по для дискретной функции выяснить частотные характеристики? 

Ну а дальше еще "трудности реализции встанут": а хватит ли быстроедествия дуины, а хватит ли памяти для хранения семплов замерянных и т.п.

 

payalnik08
Offline
Зарегистрирован: 16.12.2012

Понятно, не стоит и заморачиваться. Проще сделать последовательное включения магнитов.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Сначала нужно завершить проект, а уже потом можно и поиграться

payalnik08
Offline
Зарегистрирован: 16.12.2012

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

 Люди добрые помогите. 

Смысл в чем: после нажатия кнопки, должны поочередно включиться 8 реле. Время между включениями и время работы реле должны меняться. После включения последнего реле система должна перейти в ждущий режим, ожидая следующего нажатия кнопки.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

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

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:
(не забываем про дребезг),

Это тот случай когда "можно забыть". Если проигрывание делать через delay(), как самый простой вариант, то это снизит частоту опроса кнопки и антидребезг получится сам собой.

kisoft пишет:
потом уходим на постучать магнитами. И так до бесконечности ;)

Только при "постучать", на кнопку все одно смотреть нужно. Что-бы прекратить стукачество при отпускании :)

leshak
Offline
Зарегистрирован: 29.09.2011

не проверял, но примерно так это будет выглядить.

Заводим папку DoorChimes. В нее ложим два файла (ниже будут)

DoorChimes.ino - главный скетч

Melody.h  - сама мелодия.

Открываем DoorChimes.ino (Melody.h - откроется сам во второй вкладке среды разработки).

Подправляем номера пинов (для кнопки и нот), я взял номер "от балды", что там у вас куда подключено - не знаю.

Зливаем, слушаем (если повезет :)

DoorChimes.ino:

#define BUTTON_PIN 2 // кнопка подключена между D2 и земля

// на каки пинах у нас висят релешки-ноты
#define Do 3 // До
#define Re 4  // Ре
#define Mi 5  // Ми
#define Fa 6  // Фа
#define Sol 7 // Соль
#define La 9  // Ля
#define Ci 8  // Си

#define Do2 9 // до второй октавы

#define PAUSE A0// псевдо нота, какой-нибудь не используемый пин, для записи "пауз" в мелодии, к нему ничего не подключать


#define SEM 1000 //Semibreve длительность целой ноты в милесекундах одной ноты (вернее сколько "ждать" после удара), фактически это задает "темп"
#define PRESS_DELAY 50 // время на сколько включается реле, длительность самого удара самого удара, ноты не должны быть "короче" этого интервала




// структура описывающая ноту
typedef struct NOTE{
  byte pin; // пин который нужно включи
  unsigned long delay;// длина ноты (сколько ждать после удара молотка)
};

#include "Melody.h" // подключаем файл с мелодией


#define TOTAL sizeof(melody)/sizeof(NOTE) // вычисляем длину мелодии (сколько нот всего)




//помогалки
#define isButtonPressed !digitalRead(BUTTON_PIN)
#define BREAK_IF_BUTTON_NOT_PRESSED if(!isButtonPressed)break;


void setup(){
  digitalWrite(BUTTON_PIN,HIGH); // включаем подтяжку для кнопки
  
  //включаем, на выход ноты-релюшки. некоторые включатся несоклько раз, но это не страшно
  for(unsigned int i=0;i<TOTAL;i++)pinMode(melody[i].pin,OUTPUT);

}

void loop(){
  if(isButtonPressed){
      for(unsigned int i=0;i<TOTAL;i++){
        NOTE note=melody[i]; // читаем текущую ноту
        
        digitalWrite(note.pin,HIGH); // стукнули
        delay(PRESS_DELAY); // дали время молоточку долететь до пластины
        digitalWrite(note.pin,LOW); // отпустили
        
        BREAK_IF_BUTTON_NOT_PRESSED;         // если кнопку к отпустили прекращаем играть
        
        delay(note.delay-PRESS_DELAY); // "тянем ноту", ждем ее длительность минус "время удара" 
        
        BREAK_IF_BUTTON_NOT_PRESSED;  // еще раз проверели не отпущенна ли кнопка
              
      }
  }
}

 

Melody.h:

NOTE melody[]={ // массив состоянищий из нот, собственно наша мелодия
// каждоя строка - нота, длительность
   // Играем гамму четвертными нотами
   {Do,SEM/4},
   {Re,SEM/4},
   {Mi,SEM/4},
   {Fa,SEM/4},
   {Sol,SEM/4},
   {La,SEM/4},
   {Ci,SEM/4},
   
   
   {Do2,SEM/2}, // верхнее до, затянем на половинку
   
   {PAUSE,SEM/8}, // чуть-чуть передохнем
   
   //и пройдем гамму вниз, быстрее, восьмушками

   {Do2,SEM/8},
   {Ci,SEM/8},
   {La,SEM/8},
   {Sol,SEM/8},

   {Fa,SEM/8},
   {Mi,SEM/8},
   {Re,SEM/8},
   {Do,SEM}, // последную ноту затянем до целой
   
   {PAUSE,2*SEM} // и в конце еще два такта паузы, что при "зацикливании мелодии" (если у кого-то палец на кнопка заклинило), был небольшой перерывчик

   
};

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

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

leshak
Offline
Зарегистрирован: 29.09.2011

"Пока играет мелодия..." - смотрите во всех кинотеатрах страны :)

payalnik08
Offline
Зарегистрирован: 16.12.2012

Огромное спасибо за помощь. Все сделал как сказали. Получился файл с двумя вкладками, но при проверке выводит ошибку        (stray # in program) на всех строках где присутствует знак (#). 

leshak
Offline
Зарегистрирован: 29.09.2011

Признавайтесь, номера строк из кода руками вычищали? Или вообще оставили "как есть".

Вообщем сам-то код вы к себе правильно копировали? Свертесь с прикрепленной веткой http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii

В сообщение #2 описано как правильно "к себе код" забирать. Вы так делали?

payalnik08
Offline
Зарегистрирован: 16.12.2012

ОЙ! у меня вообще программа не такая как на картинке. У меня установлена Arduino 1.0.3

leshak
Offline
Зарегистрирован: 29.09.2011

Код 100% компилируется, вообщем "что-то повредили при копировании к себе".

Лениво счас разбиратся "что и как".

Ловите в виде .zip файла 

http://dropcanvas.com/wn0mo

leshak
Offline
Зарегистрирован: 29.09.2011

payalnik08 пишет:
ОЙ! у меня вообще программа не такая как на картинке. У меня установлена Arduino 1.0.3

Какая програма? на какой картинке? причем тут версия ArduinoIDE?

Я же вам указал номер сообщения который нужно читать #2.

Там вообще скриншоты только самого форума (который вы сейчас читаете, ни одного скриншота никаких программ - я там не вижу). Как правильно код с форума скопировать в клип-боард без постороннего мусора. У куда вы его потом в ставите Arduno 0.22, Arduno 1.0.3 или Notepad - дело вашего вкуса.

payalnik08
Offline
Зарегистрирован: 16.12.2012

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

С зипом получилось, все проверяется. Сейчас попробую залить и поиграться

leshak
Offline
Зарегистрирован: 29.09.2011

payalnik08 пишет:
Ну да все правильно, просто я еще не въехал в эту кухню. Сегодня только собрал железо и хотел поиграться с программированием. Сам я далекий от него, но желание есть. С зипом получилось, все проверяется. Сейчас попробую залить и поиграться

Не забудте поправить номера пинов (или подключите на те которые указаны в коде).

payalnik08
Offline
Зарегистрирован: 16.12.2012

Вы даже представить не можете как я прыгаю по комнате от радости. Все получилось, работает. Только в железе я сделал на кнопку 5 вольт, а не на землю и как можно задействовать 8-е реле.Подскажите для полного счастья

payalnik08
Offline
Зарегистрирован: 16.12.2012

Все 10-ю релюшку я задействовал (в программе изменил Do2- gjcnfdbk 10) Сейчас думаю над кнопкой.

leshak
Offline
Зарегистрирован: 29.09.2011

payalnik08 пишет:
Только в железе я сделал на кнопку 5 вольт, а не на землю

Если вы подключили кнопку  между пином и 5v, то вам нужно в строке 38

#define isButtonPressed !digitalRead(BUTTON_PIN)

Убрать восклицательный знак. Сделать 

#define isButtonPressed digitalRead(BUTTON_PIN)

Далее вам нужно закоментировать (или вытереть) строку 43

 digitalWrite(BUTTON_PIN,HIGH); // включаем подтяжку для кнопки

----

С кодом все. Но кнопка у вас будет ловить "помехи". Либо вообще случайно, либо "от поднесения руки", вообщем "как повезет", что-бы это предотврарить, этот же пин кнопки нужно еще резистором в 10K-20K соеденить с землей.

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

Вообщем смотрите если кнопка "к питанию", то правильно она должна так подключатся 

http://arduino.ru/tutorials/button

 

payalnik08
Offline
Зарегистрирован: 16.12.2012

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

payalnik08
Offline
Зарегистрирован: 16.12.2012

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

leshak
Offline
Зарегистрирован: 29.09.2011

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

Ну, обычно звонок именно так и работает. Как только отпустили - прекращаем играть.

Но если хотите "до конца", ну так почитайте же код. Попробуйте разобратся как он работает.

Там даже откоментированы строки которые "обрывают" игру если кнопку отпустили. Уберити их - и все (или закоментируйте).

Попробуйте их сами найти (две штуки их там, в двух-местах "может выстрелить в пианиста").

А вообще, стоило бы (я обычно так и делаю), отправить вас сначала читать раздел "Среда разработки" и "Програмирование" (в шапке сайта ссылки). Начинать нужно с чего-то более простого: как диодом помигать, как кнопку читать, как с Serial работать. Ознакомится с "какие кубики есть у этого конструктора". Посмотреть/попробовать примеры.

leshak
Offline
Зарегистрирован: 29.09.2011

payalnik08 пишет:
Я вытер две последние строки и мелодия начала играть до конца при коротком нажатии.

Одну из этих строчек - правильно вытерли. А вторую - убили "длительность нот". Будут теперь все одинаковой длины.

Там же каждая строка откоментировано что делает. Зачем же вам было убирать "теняем ноту", раз вы хотели что-бы оно не реагировало на отпускание КНОПКИ, то логично что искать/убирать нужно именно проверки кнопки?

payalnik08
Offline
Зарегистрирован: 16.12.2012

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

leshak
Offline
Зарегистрирован: 29.09.2011

Вопрос не в "надоел", а не "хочется поощрять халяву".

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

Но ведь нужно же вам (раз собрались заниматься ардуинством) с чего-то начинать учебу. Погуглить C/C++ массивы.

Или даже, первым шагом, не массивы, а просто, попробуйте добавить какой-то "счетчик" нажатий сделать. И выводить в Serial сколько раз мы сыграли мелодию (пусть и одну и ту же пока).

Потом сделайте что-бы счетчик обнулялся, к примеру, когда доходит до 5-ти.

Потом и с массивами разберемся.

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

payalnik08
Offline
Зарегистрирован: 16.12.2012

Я с вами полностью согласен, сам не люблю халявщиков. Мне интересно разобраться самому. Но если ничего не получится, могу ли я расчитывать на вашу помощь (конечно не бесплатную). Огромное спасибо за вашу помощь.
С наступающими вас праздниками.

leshak
Offline
Зарегистрирован: 29.09.2011

payalnik08 пишет:

Я с вами полностью согласен, сам не люблю халявщиков.

Да нет. Люди разные. Это всего лишь одна из стратегий поведения. Я это принимаю как устройство мира. Без раздражения.

Тут речь скорее что "я не хочу творить зло". А зло - это отбивать охоту у человека самому попытатся. Трудно удержатся и не "подсмотреть готовый ответ". А так глядишь есть шанс, что вольетесь в наши ряды :)

payalnik08 пишет:

Мне интересно разобраться самому.

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

payalnik08 пишет:

Но если ничего не получится, могу ли я расчитывать на вашу помощь (конечно не бесплатную). Огромное спасибо за вашу помощь. С наступающими вас праздниками.

Да. Конечно. Правда "за деньги" тут вообщем-то уже и делать нечего (это я уже из принципа "остановился").

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

Но, не так страшен черт.  Если "разобратся" - важнее, то попробуйте сделать то что я выше сказал, а там посмотрим "как пойдет". Я помогу-подскажу (бесплатно) :)

payalnik08
Offline
Зарегистрирован: 16.12.2012

Буду пытаться постичь сам эту науку. По крайней мере хотя бы ее азы. Книгу по программированию я скачал. Потом как вы сказали попробую счетчик и массивы. Я в правильном направлении ?

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Есть неплохая книга с кучей примеров "Arduino Cookbook" но на английском, но примеров море

payalnik08
Offline
Зарегистрирован: 16.12.2012

Спасибо, примеры это хорошо

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:
Есть неплохая книга с кучей примеров "Arduino Cookbook" но на английском, но примеров море

Книга безусловно неплохая. Я бы даже сказал "архиполезная". Вот только "для новичка ли"? Там все-таки уже скорее "тонкости AVR-ров", а не "как заменить кучу if на один switch" или "когда byte лучше int" :)

Вообщем "на полку" ее можно положить (если планируете делаеть на Arduino сложно-интерестные вещи). 

Но вот рекомендовать "вот прямо сейчас обязательно начинайте ее читать" - я бы не стал. Вам нужно сначала с языком освоится.

Кстати все время держите в уме, что Arduino-язык базируется на  C/C++. И если вы видите "что-то не понятное", например слово "#define", то узнать "что это за зверь" можно в справочнике по C/C++ с вероятностью 99%

А вот в родной документации - этого может и не быть. Вообщем "не забывайте про родителей" ;)

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

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

leshak
Offline
Зарегистрирован: 29.09.2011

payalnik08 пишет:

Буду пытаться постичь сам эту науку. По крайней мере хотя бы ее азы. Книгу по программированию я скачал. Потом как вы сказали попробую счетчик и массивы. Я в правильном направлении ?

В правильном. Давайте даже пока "про массивы" забудем. Давайте со счетчиком. Причем, наверное, не нужно пытатся это сразу всобачить в скетч звонка. Он большой и будет "перегружать вас инфой". Сделайте, File/New, там разберитесь с очередной "идеей/принципом" в заведомо упрощенном варианте. А уж когда пришло понимание "как это делать", можно смотреть "как это вставить в основной скетч". Или, если эта "идея" уже есть в "основном" - посмотреть как она там сделана.

Так, по кусочкам мы, мы упрощенно повторим написание "основного", где-то его улучшим и главное постараемся что-бы он у нас из "магии которая работает" превратился "да тут же все тривиально" :)

Давайте даже "счетчик" разобъем на еще более мелкие задачи. Попробуйте написать скетч который просто ловит нажатие кнопки и отсылает в сериал-монитор сообщение об этом "Button Pressed" (Кнопка Нажата). Научимся "следить" за тем, чем у нас скетч занимаетеся. Смотреть "как он работает". Для этого вам нужно будет почитать про digitalRead и Serial (документации на сайте будет достаточно).

Update: когда я говорю "попробуйте сделать" - я имею ввиду "попробуйте и показывайте тут что получилось". даже если "получилось частично".

payalnik08
Offline
Зарегистрирован: 16.12.2012

Согласен, будем читать.

payalnik08
Offline
Зарегистрирован: 16.12.2012

Соеденил два примера. Получил включение светодиода при нажатии кнопки и изменение нуля на единицу в порту.

 



int ledPin = 5;                 // Светодиод подключенный к вход/выходу 5
int inPin = 2;                   // кнопка на входе 2
int val = 0;                     // переменная для хранения значения
int digitalValue = 0;            // переменная для хранения считываемого значения 

void setup()
{
  pinMode(ledPin, OUTPUT);       // устанавливает режим работы - выход для го вход/выхода (pin)
  pinMode(inPin, INPUT);         //  устанавливает режим работы - вход для 2го вход/выхода (pin)
  Serial.begin(9600);            // открываем порт
}
 
void loop()
{
  val = digitalRead(inPin);      // считываем значение с входа для светодиода
  digitalWrite(ledPin, val);     // устанавливаем значение на светодиоде равным значению входа кнопки
 

  digitalValue = digitalRead(2);  // считываем данные с входа 2 для передачи
  Serial.println(digitalValue);  // выводим 

delay(100);                       //затормозим бег 0
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

 

Очень неплохо.

Но я покритикую скетч :)  Не потому что "все плохо".  На самом деле - неплохо. главное что работает. Да еще и

В.С. Высоцкий пишет:

Азарт меня пьянил, но, как ни говори, 
Я тормозил на скользких поворотах! 

не забыли ;)

Итак, что тут можно "сделать получше". Вообщем-то все советы "не обязательны". Скетч-то уже работает :), но лучше "правильный стиль" вырабатывать сразу. В будущем съекономит кучу времени при поиске трудноуловимых ошибок.

 

1. Типы данных

Тут лучше применять не int, а byte. Для данного скетча это "не критично", на работу не повлияет но лучше изначально привыкать подбирать подходящий типа данных осознанно. Не больше и не меньше чем нужно для конкретной задачи. Это убережет в будущем от излишнего расхода памяти и трудноуловимых ошибок переполнения.

Идем http://arduino.ru/Reference находим "типы данных" и читаем какие они бывают (желательно все, не так и много их там). Желательно ПОНЯТЬ почему тут byte будет более подходящим, а не потому что "я так сказал" :)

2. Область видимости переменных

Переменную val лучше объявить внутри самого loop(). Больше она нигде не используется, между "проходами loop" запоминать ее состояние не требуется, поэтому нет никакой необходимости "засорять" глобальное простраство имен. На больших скетчах, можно часы провести в поисках глюка и той функции меняет какую-то глобальную переменную "когда вы не ждете".

3. Неизменяемые переменные.

Замечательно что вы решили вынести номера пинов в заголовок файла. Это "хороший стиль" :)  Действительно "магические цифры" в коде - это зло. Гораздо лучше когда есть "говорящие имена". Такой код гораздо легче сопровождать.

Правда, в строке 19, применили-таки "магическое число 2", но, я так понимаю, это просто опечатка. 

Но давайте присмотримся к ledPin и inPin. Явно мы предполагаем что они не будут у нас менятся во время работы скетча. По крайней мере "не должны". Можно сообщить об этом компилятору добавив в объевление ключевое слово const . Тогда компилятор будет "следить за этим" и если мы где-то попытаемся, случайно/ошибочно, их поменять он сразу нам об этом скажет. И не даст залить такой ошибочный скетч в дуину (а без const, мы узнаем об этом только по глюкам и потратим время на поиск "где-же мы случайно изменили их").

Попробуйте добавить к ним const, а потом попробуйте их изменить где-нибудь в коде :)

Но, в данном случае лучше, для них, использовать даже не переменные, а #define. Разница в том, что под переменные выделяется "ячейка памяти" и тратятся такты на ее чтение,  а #define, это как-бы "автозамена" которая выполняется в перед компиляцией програмы. Если вы написали #define LED_PIN 5, то это приведет к тому, что перед копиляцией програмы по всему коду будет искатся имя "LED_PIN", где найдет заменить его на цифру 5 и только потом начнет компилировать програму. Поэтому

 

#define LED_PIN 5
.....
digitalWrite(5,HIGH);
digitalWrite(LED_PIN,HIGH); // эта строка АБСОЛЮТНО идентична, с точки зрения компилятора, предыдущей строке. Вначале он заменит LED_PIN на 5 и только потом начнет компилировать

 

 

То есть мы c помощью #define убиваем двух зайцев сразу - с одной стороны мы избавляемся от "магических цифр" (и легко можем поменять пин, не лазя по всему коду изменяя его), с другой - нам это "ничего не стоит" (не выделяется память, не тратится время на чтение).

3. Дублирование переменных.

Если вы посмотрите, то val и digitalValue - у вас выполняют абсолютно идентичные задачи. Более того, к моменту когда вы начали использовать digitalValue - вам значение val которое вы сохранили в сроке 15-ть уже совершенно не нужно. Его можно выкинуть. То есть второе чтение - тоже выполнять в переменную val. А digitalValue - просто выкинуть из скетча вообще.

4. Дублирование чтение порта.

Зачем нам строка 19? Мы же уже прочитали порт в 15-ть. И сохранили его состояние в val. От того что мы его использовали в строке 16-ть - оно не "испортилось". Более того, если у нас стоит задача выводить в serial "что же мы установили сейчас на led" - второе чтение вредно. Между первым и вторым чтение, какие-то микросекунды да проходят. И кнопка, к моменту второго чтения - все-таки может изменить свое значение. А значит у нас возникнет ситуация что на светик мы отобразили одно, а в Serial отчитались о другом.

 

Итого (что желательно сделать):

понять и применить более экономные типы для переменных. Переменную val сделать локальной. Номера пинов из переменных переделать в #define, выбросить лишние переменные и чтения порта.

leshak
Offline
Зарегистрирован: 29.09.2011

И еще, совсем мелочный коментарий: строка 9   pinMode(inPin, INPUT); - не обязательна. По умолчанию, если мы не сказали обратного, ВСЕ пины уже включены на INPUT сразу после подачи питания.

Но говорить "переделайте" - я не буду. Писать ее или нет - скорее дело личных предпочтений. С одной стороны "она не делает ничего полезного", с другой - такой код легче читать. Сразу видно какие порты мы используем и как (когда берешь скетч, то первым делом смотришь в setup, кого-куда выставляют).

payalnik08
Offline
Зарегистрирован: 16.12.2012

Азарт конечно есть. Но я читаю читаю, в голове все путается. Самое страшное когда пишу код не понимаю, что пишу, а просто отталкиваюсь от примеров.

payalnik08
Offline
Зарегистрирован: 16.12.2012

Как можна объявить все PIN выходами, чтобы не перечислять



void setup() {
 pinMode(3,OUTPUT);
 pinMode(4,OUTPUT);
 pinMode(5,OUTPUT);
 pinMode(6,OUTPUT);
 pinMode(7,OUTPUT);
 pinMode(8,OUTPUT);
 pinMode(9,OUTPUT);
 pinMode(10,OUTPUT);
}
void loop() {

  digitalWrite(5,HIGH);
  digitalWrite(6,HIGH);  

delay (2000);


digitalWrite(7,1);
delay (4000);
digitalWrite(8,1);
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

leshak, п.3. я бы не рекомендовал, особенно для новичков.

Вместо конструкции:

{
  byte val;
  val = digitalRead(...);
  ...
  val = digitalRead(...):
}

Я бы рекомендовал:

{
  {
    byte val;
    ...
    val = digitalRead(...);
    ...
  }
  {
    byte val;
    ...
    val = digitalRead(...);
    ...
  }
}

А по большому счету не стал бы это рекомендовать совсем.

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

Спорить не буду, просто не рекомендую. А еще это личный опыт, а  он у меня немаленький.

 

leshak
Offline
Зарегистрирован: 29.09.2011

kisoft пишет:

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

Вы правы. В обычных случаях экономить повторно используя переменные - не стоит. Лучше пару байт потратить но иметь более понятный код. Но....

в данном случае мы выполняем одно и тоже действие. Читаем один и тот же пин. Так что тут это можно назвать скорее не "повторное использование", а "освежили значение переменной до актуального состояния". Именно в данному случае введение второй переменной - скорее сбивает. Нужно вникать "а в чем между ними различия?". Даже коментарий-описание у них практически идентичный. В крайнем случае, если хочется две переменные, то лучше было их назвать val1 и val2. Что-бы имя подсказывало что они "очень родствены".

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012
void setup() {
 pinMode(3,OUTPUT);
 pinMode(4,OUTPUT);
 pinMode(5,OUTPUT);
 pinMode(6,OUTPUT);
 pinMode(7,OUTPUT);
 pinMode(8,OUTPUT);
 pinMode(9,OUTPUT);
 pinMode(10,OUTPUT);
}
void loop() {

  digitalWrite(5,HIGH);
  digitalWrite(6,HIGH);  

delay (2000);


digitalWrite(7,1);
delay (4000);
digitalWrite(8,1);
}

Можно заменить на разные варианты:

void setup() {
  for( byte i = 3; i <= 10; ++i )
  {
    pinMode(i,OUTPUT);
  }
}

другой вариант:

const byte pin_array[] =
{
  3,4,5,6,7,8,9,10
};

#define pin_array_kol (sizeof(pin_array)/sizeof(pin_array[0]))

void setup() {
  for(byte i=0; i < pin_array_kol; ++i )
  {
    pinMode( pin_array[ i ],OUTPUT);
  }
}

Выбор варианта зависит от многих факторов.

В частности первый вариант ограничен тем, что номера пинов должны быть последовательностью.

Второй вариант плох тем, что массив занимает место в памяти. А если он больше нигде не используется, то память расходуется впустую.

И наконец - твой вариант, он не такой и плохой. Иногда - он - лучшее решение.

Всё зависит от использования, эффективности, наличия памяти.

Есть такая штука, как оптимизация. Как правило, если программе нужно быстрее работать, то программа занимает больше места, а если надо занимать меньше памяти, то она может работать дольше.

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

 

leshak
Offline
Зарегистрирован: 29.09.2011

payalnik08 пишет:

Как можна объявить все PIN выходами, чтобы не перечислять

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

Для этого вам нужно: объявить массив байтов. Положить в него номера пинов. А дельше, в setup(), пробежатся c помощью for по этому массиву.

Собствено отсюда ясно "что читать нужно".

http://arduino.ru/Reference/Array

Собственно там даже пример есть. Именно с пинами. Только они выводят в Serial, а вы будете делать pinMode, вместо print.

P.S. А если бы бегло почитали весь раздел "програмирование", то вспомнилибы "что-то такое я где-то видел" :)

step962
Offline
Зарегистрирован: 23.05.2011

Если хочется уж совсем коротко, то код

void setup() {
 pinMode(3,OUTPUT);
 pinMode(4,OUTPUT);
 pinMode(5,OUTPUT);
 pinMode(6,OUTPUT);
 pinMode(7,OUTPUT);
 pinMode(8,OUTPUT);
 pinMode(9,OUTPUT);
 pinMode(10,OUTPUT);
}

можно заменить на

void setup() {
 DDRD |= 0xF8;
 DDRB |= 0x07;
}

На выход будут сконфигурированы пины с D3 по D10. D0-D2 и D11-D13 останутся "слушающими"

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

step962 пишет:

можно заменить на

void setup() {
 DDRD |= 0xF8;
 DDRB |= 0x07;
}

Конечно, можно и даже правильно, НО. Я бы не советовал применять такие конструкции без понимания сути вопроса, поэтому советую, для того, чтобы это осознано применить, "вкурить" несколько статей:

1. Про управление портами (ногами) AVR

2. Про соответствие портов и ног ардуины (pin mapping)

3. Про битовые операции

И еще. При таком подходе забудте про переносимость программы - будет работать только на той плате (том проце), для которого Вы возмете "pin mapping"

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

Поинтересуйтесь (у Гугля) про функции с переменным числом параметров:

void pinOutput(byte pin, ...) //следите, чтобы все аргументы были типа byte
{
  byte *p=&pin; //берем адрес первого аргумента
  while (*p) // делаем, пока не наступит нулевой указатель - значит аргуметов больше нет
  {
    pinMode( *p, OUTPUT);
    p++;
  }
}

//вызов

pinOutput( 2, 3, 4, 5);

На железе не проверял, возможно, нужно взять тип int.

leshak
Offline
Зарегистрирован: 29.09.2011

to step962 AlexFisher

Э... ээээ!!! Стоп. Стоп!!!!

Вы чего? Какия прямая запись в порт? Какие функции с переменным числом параметров!!!!! 

Человек пишет свою первую програму!!!! Выясняет что такое массивы и как пользоватся циклами. Разбираемся чем byte от int отличается.

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

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