При работе с ИК-приемником появились проблемы. Выяснил, что косяк программный, поскольку тестовые скетчи работают нормально. В моей же программе работать отказывается, весь прием идет неверно. Принятые слова все разные, хотя должно повторяться только одно слово. Возможно, проблема связана с прерываниями. Кто-нибудь сталкивался с подобным?
Таймер:
#include <AnalogButtons.h>
#include <SevenSeg.h>
#include <IRremote.h>
decode_results results;
const int recvPin = 17;
IRrecv irrecv(recvPin); // пин для ИК-приемника
#define ANALOG_PIN A7 // пин аналоговой кнопки
#define zummer 13 // пин пищалки
#define pyro A0 // пин пиропатрона
#define RED A1 // красный цвет
#define BLUE A2 // синий цвет
#define T_PERIOD 1000 // отсчет 1 секунды в таймере
#define T_zummer 150 // время писка
byte mode = 1; // стартуем с режима FUSE
byte team = 0; //1-красные, 2-синие
bool out = false; // флаг для выхода из режима захвата
bool LB = false; // флаг левой кнопки
bool RB = false; // флаг правой кнопки
bool SB = false; // флаг малой кнопки
bool SBHold = false; // флаг удержания малой кнопки
bool BB = false; // флаг большой кнопки
bool BBHold = false; // флаг удержания большой кнопки
uint16_t Total = 0; // общее время в секундах
char str[5]; // промежуточная переменная для колхозной строки
uint16_t RedTime = 0; // время красных
uint16_t BlueTime = 0; // время синих
SevenSeg disp(12,11,10,9,8,7,6); // пины индикатора ABCDEFG
const int numOfDigits=4; // число разрядов
int digitPins[numOfDigits]={5,4,3,2}; // порядок следования разрядов слева направо
AnalogButtons analogButtons(ANALOG_PIN, INPUT); // создаем переменные кнопок с уровнями срабатывания
Button b1 = Button(713, &b1Click);
Button b2 = Button(235, &b2Click);
Button b3 = Button(464, &b3Click, &b3Hold);
Button b4 = Button(1023, &b4Click, &b4Hold);
void setup() {
irrecv.enableIRIn();
disp.setDigitPins(numOfDigits, digitPins);
disp.setActivePinState(HIGH,HIGH);
disp.setTimer(1) ;
disp.startTimer();
analogButtons.add(b1);
analogButtons.add(b2);
analogButtons.add(b3);
analogButtons.add(b4);
pinMode(zummer, OUTPUT);
pinMode(RED, OUTPUT);
pinMode(BLUE, OUTPUT);
Serial.begin(115200); // для отладки
}
ISR(TIMER1_COMPA_vect){
disp.interruptAction();
analogButtons.check();
}
void b1Click() { //LB
LB = true;
}
void b2Click() { //RB
RB = true;
}
void b3Click() { //SB
SB = true;
}
void b3Hold() { //SB Hold
SBHold = true;
}
void b4Click() { //BB
BB = true;
}
void b4Hold() { //BB Hold
BBHold = true;
}
void loop(){
if(mode == 1)disp.write("FUSE");
if(mode == 2)disp.write("FLAG");
if(BB) //По нажатию большой кнопки выбираем режим
{
mode++;
if (mode > 2) mode = 1;
BB = false;
}
if(SB) //По нажатию малой кнопки заходим в режим
{
SB = false;
switch (mode) //выбор режима
{
case 1: MODE_1(); break; //Выбор режима 1
case 2: MODE_2(); break; //Выбор режима 2
case 3: MODE_3(); break; //Выбор режима 2
default: break;
}
}
}
void MODE_1(){ // режим бомбермана
byte mm = 0; // минуты
byte ss = 0; // секунды
byte def = 5; // время разминирования
bool defuse = false; // флаг разминирования
uint32_t timer = 0; // переменная таймера
byte counter = 0; // считаем время удержания разминирования
while(!SB){ //устанавливаем секунды
if(ss < 10){
snprintf(str, 5, "---%d", ss);
disp.write(str);
}
if(ss >= 10){
snprintf(str, 5, "--%d", ss);
disp.write(str);
}
if(BB){
ss++;
BB = false;
}
if(BBHold){
ss = ss+5;
BBHold = false;
}
if(ss > 59) ss = 0;
}
SB = false;
while(!SB){ //устанавливаем минуты
if(mm < 10){
snprintf(str, 5, "-%d--", mm);
disp.write(str);
}
if(mm >= 10){
snprintf(str, 5, "%d--", mm);
disp.write(str);
}
if(BB){
mm++;
BB = false;
}
if(BBHold){
mm = mm+5;
BBHold = false;
}
if(mm > 99) mm = 0;
}
SB = false;
while(!SB){ //устанавливаем время разминирования
if(def < 10){
snprintf(str, 5, "de0%d", def);
disp.write(str);
}
if(def >= 10){
snprintf(str, 5, "de%d", def);
disp.write(str);
}
if(BB){
def++;
BB = false;
}
if(def > 25) mm = 0;
}
SB = false;
Total = 60*mm + ss; // посчитали общее время
while(!BBHold){
showTime(Total);
}
BBHold = false;
while(Total > 0 && defuse == false){
if(millis() - timer >= T_PERIOD){ // таймер на millis()
timer = millis(); // сброс
digitalWrite(zummer, HIGH);
Total--;
if(BBHold){
counter++;
if(counter == def) defuse = true;
BBHold = false;
}
else counter = 0;
if(Total & 1){
digitalWrite(RED, HIGH);
digitalWrite(BLUE, LOW);
} else{
digitalWrite(RED, LOW);
digitalWrite(BLUE, HIGH);
}
}
if(millis() - timer >= T_zummer){
digitalWrite(zummer, LOW); // отключение зуммера
}
if(Total == 0){
digitalWrite(pyro, HIGH); // подрыв
while(!SB){
disp.write("");
}
SB = false;
}
if(defuse){
while(!SB){
showTime(Total);
if (millis() - timer >= T_zummer) { // таймер на millis()
timer = millis(); // сброс
digitalWrite(zummer, !digitalRead(zummer));
}
}
SB = false;
BB = false;
SBHold = false;
BBHold = false;
}
showTime(Total);
}
defuse = false;
digitalWrite(pyro, LOW);
digitalWrite(zummer, LOW);
digitalWrite(RED, LOW);
digitalWrite(BLUE, LOW);
mm = 0; // обнуляем минуты
ss = 0; // обнуляем секунды
defuse = false; // снимаем флаг разминирования
counter = 0; // обнуляем время удержания разминирования
}
void MODE_2(){ // режим захвата флага
byte mm = 0; // минуты раунда
byte ss = 0; // секунды раунда
byte counter = 0; // считаем время удержания для выхода из режима
uint32_t timer = 0; // переменная таймера
while(!SB){ //устанавливаем секунды
analogButtons.check();
if(ss < 10){
snprintf(str, 5, "---%d", ss);
disp.write(str);
}
if(ss >= 10){
snprintf(str, 5, "--%d", ss);
disp.write(str);
}
if(BB){
ss++;
BB = false;
}
if(BBHold){
ss = ss+5;
BBHold = false;
}
if(ss > 59) ss = 0;
}
SB = false;
while(!SB){ //устанавливаем минуты
if(mm < 10){
snprintf(str, 5, "-%d--", mm);
disp.write(str);
}
if(mm >= 10){
snprintf(str, 5, "%d--", mm);
disp.write(str);
}
if(BB){
mm++;
BB = false;
}
if(BBHold){
mm = mm+5;
BBHold = false;
}
if(mm > 99) mm = 0;
}
SB = false;
Total = 60*mm + ss; // посчитали общее время
disp.write("----");
while(Total > 0){ // крутимся до тех пор, пока время не кончилось или не остановили игру
if(SBHold){ // выходим из цикла
Total = 0;
SBHold = false;
}
if(LB){ // снимаем флаг левой кнопки
team = 1;
LB = false;
}
if(RB){ // снимаем флаг правой кнопки
RB = false;
team = 2;
}
if(irrecv.decode(&results)){
Serial.println(results.value, HEX);
if(results.value == 0x801) team = 1;
if(results.value == 0x811) team = 2;
irrecv.resume();
}
if(team != 0){
if(millis() - timer >= T_PERIOD){ // таймер на millis()
timer = millis(); // сброс
digitalWrite(zummer, HIGH); // начинаем пищать
Total--;
if(team == 1){
RedTime++;
showRedTime();
digitalWrite(RED, HIGH);
digitalWrite(BLUE, LOW);
}
if(team == 2){
BlueTime++;
showBlueTime();
digitalWrite(RED, LOW);
digitalWrite(BLUE, HIGH);
}
}
}
if(millis() - timer >= T_zummer){
digitalWrite(zummer, LOW); // отключение зуммера
}
}
digitalWrite(zummer, LOW); // отключение зуммера шоб не пищал после выхода из цикла
while(!SB){
analogButtons.check();
if(LB){ // снимаем флаг левой кнопки
team = 1;
LB = false;
}
if(RB){ // снимаем флаг правой кнопки
RB = false;
team = 2;
}
if(team == 1){
showTime(RedTime);
digitalWrite(RED, HIGH);
digitalWrite(BLUE, LOW);
}
if(team == 2){
showTime(BlueTime);
digitalWrite(RED, LOW);
digitalWrite(BLUE, HIGH);
}
}
SB = false;
digitalWrite(RED, LOW);
digitalWrite(BLUE, LOW);
mm = 0; // обнуляем минуты
ss = 0; // обнуляем секунды
}
void MODE_3(){
disp.clearDisp();
}
void showTime(int val){ // показывалка времени с колхозными строчками
if(val > 599) disp.writeClock(val); // выводим без колхоза
if(val/60 < 10 && val%60 > 9){ // колхозим вывод 0, когда время меньше 10 минут и больше 59 секунд
snprintf(str, 5, "0%d%d", val/60, val%60);
disp.write(str);
}
if(val/60 <= 9 && val%60 <= 9){
snprintf(str, 5, "0%d0%d", val/60, val%60);
disp.write(str);
}
if(val <= 59 && val%60 > 9){
snprintf(str, 5, "00%d", val%60);
disp.write(str);
}
if(val <= 59 && val%60 <= 9){
snprintf(str, 5, "000%d", val%60);
disp.write(str);
}
if(val <= 9){ // закончили колхоз строки с нулями
snprintf(str, 5, "000%d", val%60);
disp.write(str);
}
}
void showRedTime(){ // показывалка времени красных с колхозными строчками
if(RedTime <= 9){
snprintf(str, 5, "0%d--", RedTime);
disp.write(str);
}
if(RedTime > 9 && RedTime <= 59){
snprintf(str, 5, "%d--", RedTime);
disp.write(str);
}
if(RedTime > 59 && RedTime/60 < 10){
snprintf(str, 5, "0%d--", RedTime/60);
disp.write(str);
}
if(RedTime > 59 && RedTime/60 > 9){
snprintf(str, 5, "%d--", RedTime/60);
disp.write(str);
}
}
void showBlueTime(){ // показывалка времени синих с колхозными строчками
if(BlueTime <= 9){
snprintf(str, 5, "--0%d", BlueTime);
disp.write(str);
}
if(BlueTime > 9 && BlueTime <= 59){
snprintf(str, 5, "--%d", BlueTime);
disp.write(str);
}
if(BlueTime > 59 && BlueTime/60 < 10){
snprintf(str, 5, "--0%d", BlueTime/60);
disp.write(str);
}
if(BlueTime > 59 && BlueTime/60 > 9){
snprintf(str, 5, "--%d", BlueTime/60);
disp.write(str);
}
}