mp3-плеер с управлением от тактовых кнопок, нужна помощь
- Войдите на сайт для отправки комментариев
Здравствуйте!
По традиции вопрос от новичка - просьба в ответ не макать лицом в грязь, а по возможности направить, куда смотреть..)
С ардуинкой только начал ознакомление, с базовыми функцииями разобрался, теперь ищу помощи в написании скетча для следующей задачи (вариация мп3 плеера):
Управление осуществляется 3 кнопками, кнопки 2 и 3 одновременно нажаты быть не могут. Кнопка 1 переключает треки (точнее дорожки, сделанные из кучи треков, записанные в один файл непрерывным потоком). Кнопки 2 и 3 включает громкость соответственной дорожки, одновременно работать не могут. Каждой дорожке присвоена своя кнопка громкости, т.е. кнопка 2 включает громкость при нажатой кнопке 1, а кнопка 3 - при отжатой.
Матрица режимов кнопок (при которых есть определенное заданное действие), остальные возможные комбинации кнопок не делают ничего:
1) нажата только кнопка 1
2) нажаты кнопки 1 и 2
3) нажата кнопка 3
4) все кнопки отпущены
Задача - отслеживать состояние кнопок, в случае удержания кнопок действие должно быть запущено и продолжаться (а не начинаться заново каждый раз либо меняться при проверке состояния).
Пробовал разные варианты, но ничего толкового не получается, поэтому очень надеюсь на помощь знающих людей. Есть у меня подозрение, что код должен получиться достаточно простой, но я уже запутался в этих флагах, состояниях и попытках избежать дребезга.
Компилятор не ругается, но сдается мне, что нифига не правильно я написал :)
На железяке еще не пробовал - мп3плеер еще не приехал, но уже на подходе).
Спасибо!
01 |
#include <DFPlayer_Mini_Mp3.h> |
02 |
#include <SoftwareSerial.h> |
03 |
SoftwareSerial mySerial(10, 11); // RX, TX |
04 |
const int songPin = 5; // кнопка "song" |
05 |
const int song1volPin = 6; // кнопка "громкость song1" |
06 |
const int song2volPin = 7; // кнопка "громкость song2" |
07 |
int regim = 0; |
08 |
int flag = 0; |
09 |
10 |
11 |
//переменные |
12 |
int song = 0; //переменная для хранения данных с кнопки "трек" |
13 |
int song1vol = 0; //переменная для хранения данных с контакта контроля состояния тригеров дверей |
14 |
int song2vol = 0; //переменная для хранения данных с контакта реле бензонасоса |
15 |
void setup () { |
16 |
Serial .begin(9600); //для отладки |
17 |
mySerial.begin(9600); //для общения с мп3плеером |
18 |
pinMode (songPin, INPUT); |
19 |
pinMode (song1volPin, INPUT); |
20 |
pinMode (song2volPin, INPUT); |
21 |
mp3_set_serial ( Serial ); |
22 |
} |
23 |
|
24 |
void loop () |
25 |
{ |
26 |
song = digitalRead(songPin); //сохраняем состояние с кнопки song |
27 |
song1vol = digitalRead(song1volPin); //с кнопки song1vol |
28 |
song2vol = digitalRead(song2volPin); //с кнопки song2vol |
29 |
|
30 |
if (song == HIGH && flag == 0) //кнопка song нажата |
31 |
{ |
32 |
regim ++; |
33 |
flag = 1; |
34 |
if (regim>2) |
35 |
{ |
36 |
regim = 1; |
37 |
} |
38 |
} |
39 |
if (song == LOW && flag == 1) //кнопка song не нажата |
40 |
{ |
41 |
regim ++; |
42 |
flag = 0; |
43 |
} |
44 |
if (regim == 1) |
45 |
{ |
46 |
if (song==HIGH&&song1vol==HIGH) //нажата также кнопка song1vol |
47 |
{ |
48 |
mp3_play (1); |
49 |
delay(5); |
50 |
mp3_set_volume (15); //0~30 |
51 |
mp3_single_loop; |
52 |
} |
53 |
else if (song==HIGH) //любые иные комбинации с нажатой кнопкой song |
54 |
{ |
55 |
mp3_play (1); |
56 |
delay(5); |
57 |
mp3_set_volume (0); //0~30 |
58 |
mp3_single_loop; |
59 |
} |
60 |
} |
61 |
|
62 |
if (regim == 2) |
63 |
{ |
64 |
if (song == LOW && song2vol == HIGH ) //нажата кнопка song2vol |
65 |
{ |
66 |
mp3_play (2); |
67 |
delay(5); |
68 |
mp3_set_volume (15); //0~30 |
69 |
mp3_single_loop; |
70 |
} |
71 |
|
72 |
else if (song==LOW) //иные комбинации при отжатой кнопке song |
73 |
{ |
74 |
mp3_play (2); |
75 |
delay(5); |
76 |
mp3_set_volume (0); //0~30 |
77 |
mp3_single_loop; |
78 |
} |
79 |
} |
80 |
} |
Я упростил Ваш код (убрал библиотеки которых у меня нет но они и не нужны для проверки алгоритма работы кнопок) для проверки в протеусе, немного подправил. Кнопки работают так как Вы описали. Посмотрите и если подойдет вместо сериал подставте свой код. На кнопки нужно сделать подтяжку, а вообще желательно замыкать на минус, догда подтяжка ставится програмно.
Проверил, действительно, все работает, хотя и не совсем так, как я планировал (допускаю, что я некорректно сформулировал задачу).
Есть ли возможность подправить код таким образом, чтобы состояние кнопок возвращалось только один раз (собственно при смене состояний), т.е. если кнопка остается нажатой, действие, вызываемое этой кнопкой, должно выполниться один раз, и дальше система ждет изменения состояния кнопок.
Т.е. грубо говоря, в мониторе порта я буду видеть только одно сообщение "1=0" или "3=1".
У меня собственно с этим и есть основной затык, т.к. пока не понимаю, как делать такие проверки.
В данном варианте кода, насколько я понимаю, флаг присвается каждый раз при проверке состояния кнопок, и запускается соответствующая функция, мне же нужно, чтобы после присвоения флага, следующий флаг бы присваивался только от иного состояния.
Не уверен, что понятно изъясняюсь, но как по другому сказать пока не могу сформулировать...(
Вы задали 4 условия
Условия выполняются, все верно, но каждый раз при проверке состояния кнопок и срабатывании одного из условий (например, нажаты кнопка 1 и 2), функция выполняется заново. Или это происходит именно изза наличия дребезга? А как в данном случае лучше сделать антидребезг? По логике мне нужно считать несколько значений, и если они одинаковые, то вызывать необходимую функцию... но я не знаю, как это сделать правильно :(
Либо делать проверку режимов при помощи функций boolean, но с ней я пока не разобрался.
Может я чегото не понимаю но - Если Вы нажали и держите кнопки 1 и 2 то условие 2 выполняется если отпустили то условие 4. И контролер каждый раз пробегая по loop проверяет, а не изменилось ли положение сигналов. Или Вам надо после кратковременного нажатия и отпускания кнопок 1 и 2 выполнения 2го условия - тогда вопрос как долго оно должно выполняться. По поводу Ваших слов (функция выполняется заново) то на этом и построена работа контролера, и чем с большей частотой он это делает тем лучше. В первом посте Вы очень четко сформулировали задачу по пунктам 1.2.3.4, сделайте это еще раз по пунктам как должно быть.
Возможно дело в выполняемой функции, но алгоритм, который есть сейчас, работает не корректно. В данном случае кнопка song переключает дорожки, т.е. если нажата и удерживается кнопка, то должна запуститься Дорожка 1, после чего программа должна ждать, пока не будет отпущена кнопка, чтобы переключить дорожку. Сейчас же при нажатии и удержании кнопки или при отпущенной кнопке дорожка запускается по новой при каждом цикле проверки. А мне нужно придумать проверку таким образом, чтобы можно было давать команду плееру таким образом, чтобы трек запускался и играл непрерывно дорожку до тех пор, пока не произойдёт смена состояния кнопки (с нажатой и удерживаемой на отпускание или с отпущенной на нажатую и удерживаемую). Ну и соответственно какой-то подходящий антидребезг - я пока не могу придумать, как его сделать((
Скнопками громкости схожая ситуация: нажатие и удержание должно включать громкость, и при удержании кнопки она не должна меняться до отпускания кнопки. Сейчас же каждый цикл проверки включает и выключает громкость.
Надеюсь, что теперь стало понятнее то, что я пытаюсь сделать..
Понял. Попробуйте так
Спасибо большое, что помогли решить вопрос, допили программу, теперь работает как надо!)
Если вдруг кому-то понадобится скетч для DF Player, можно взять мой вариант. Особоенность - всего два трека, переключаются кнопкой "song", проигрывает до конца трека и останавливается. Кнопка "song_vol1" включает громкость, когда играет трек1, кнопка "song_vol2" включает громкость, когда играет трек2.
Еще раз спасибо огромное за помощь!!