Проблема не сохранения предыдущего значения при отправке по блютусу

Управление светодиодами с помощью кнопок и Bluetooth одним и тем же методом

Теперь проблема:

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

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

Код: внизу этой страницы

спасибо

сейчас это неправильно в видео

Фото для моего проекта

 #define CLK 10
 #define CLKI 9
 #define LD 8
 #define SO 11
 #define SER 12

 byte ledstates;
 byte copy=0;
 unsigned long bt_leds_timestamp=0;
 byte bt_leds_activated=0;

 void setup(){
   Serial.begin(9600);
   pinMode(CLK,OUTPUT);
   pinMode(CLKI,OUTPUT);
   pinMode(LD,OUTPUT);
   pinMode(SO,INPUT);
   pinMode(SER,OUTPUT); 
  }

 void loop(){
  if (Serial.available()>0){
  message();
 }
  shift_In();
  shift_out(ledstates);

  if(bt_leds_activated && millis()-bt_leds_timestamp > 2000){
  ledstates &= ~bt_leds_activated;
  shift_out(ledstates);
   bt_leds_activated = 0;
  }
 }

 void message(){
  if(Serial.available()){      // Отправляем данные только при их получении:
  char data = Serial.read();        // Чтение входящих данных & хранить в данных
  Serial.print(data);          //Напечатайте значение внутри данных в последовательном мониторе

  switch (data){
  case 'A' :
    bt_leds_activated |= 1;
    break; 
  case 'B' :
    bt_leds_activated |= 2;
    break;
  case 'C' :
    bt_leds_activated |= 4;
    break;
  case 'D' :
    bt_leds_activated |= 8;
    break;
  case 'E' :
    bt_leds_activated |= 16;
    break;
  case 'F' :
    bt_leds_activated |= 32 ;
    break;
  case 'G' :
    bt_leds_activated |= 64;
    break;
  case 'H' :
    bt_leds_activated |= 128;
    break;
  default   : return; }    
  }
   ledstates |= bt_leds_activated;
   shift_out(ledstates);
   bt_leds_timestamp = millis();
  }

 void shift_out (byte copy){
  digitalWrite(LD, LOW);
  shiftOut(SER,CLK,MSBFIRST,copy);
  digitalWrite(LD, HIGH);
  delay(100);
 }

 void shift_In(){
  digitalWrite(CLKI,HIGH);
  digitalWrite(LD,HIGH);
  digitalWrite(LD,LOW);
  digitalWrite(LD,HIGH);
  digitalWrite(CLK,HIGH);
  digitalWrite(CLKI,LOW);
  byte buttonstates = shiftIn(SO,CLK,MSBFIRST); //читаем состояния кнопок в локальной переменной
  digitalWrite(CLKI,HIGH);
  for(int i=0;i<8;i++){ // перебираем все 8 бит состояния кнопки
    if(!(copy & (1<<i)) && (buttonstates & (1<<i))){ // проверяем, является ли старое состояние кнопки (в копии) равным нулю, а новое состояние кнопки равно 1 (для текущего контрольного бита)
        ledstates ^= 1<<i; // переключаем соответствующий бит в переменной ledstates (будет смещен позже в функции loop())
    }
  }
  copy = buttonstates;
  delay(10); // задержка для устранения дребезга
  }

, 👍0


1 ответ


Лучший ответ:

0

C имеет оператор "Исключающее ИЛИ", который имеет вид ^. Вы можете использовать это вместо |, чтобы он переключал бит, а не всегда устанавливал его:

case 'A' :
    bt_leds_activated ^= 1;
    break; 

С ^, если вы ИЛИ 0 с 1, вы получите 1. Если вы ИЛИ 0 с 0, вы получите 0. Если вы ИЛИ 1 с 1, вы получите 0 .

Это означает, что каждый раз, когда вы отправляете бит A, один из битов bt_leds_activated будет инвертироваться. Если это 0, то станет 1. Если это 1, то станет 0.

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

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

Поэтому просто полностью отмените bt_leds_activated и используйте ledstates:

case 'A':
    ledstates ^= 1;
    break;

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

,

Никаких изменений в состоянии проекта после редактирования кода. неправильно еще. Эй, чувак, пожалуйста, посмотри видео, чтобы понять ошибку. Спасибо https://youtu.be/EcpJeewE1AU, @Khalid Abu-Khadija

Я думаю, ваша проблема в том, что у вас есть два набора состояний, хотя на самом деле вам нужен только один., @Majenko

Каково решение . Вы можете отредактировать этот баг. Я думаю, ошибка в этом условии if, @Khalid Abu-Khadija

if(bt_leds_activated && millis()-bt_leds_timestamp > 2000){ ledstates &= ~bt_leds_activated; shift_out (состояния светодиодов); bt_leds_activated = 0; }, @Khalid Abu-Khadija

Полностью забудьте о bt_leds_activated. Просто используйте ledstates везде., @Majenko

Отредактируй свой ответ братан, а потом объясни мне на примере, @Khalid Abu-Khadija

ledstates |= bt_leds_activated; shift_out (состояния светодиодов); bt_leds_timestamp = миллис();, @Khalid Abu-Khadija

Как насчет этих строк, @Khalid Abu-Khadija

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

Я хочу время задержки при отправке символа после символа, @Khalid Abu-Khadija

Я не знаю, что это значит., @Majenko

Во-первых: спасибо за редактирование моего кода, теперь код работает отлично. Но этот код является чистым кодом или нет. И тогда, например, при отправке символа A по Bluetooth в реальном процессе отправки требуется временная задержка между отправленным значением и последующим 2-м значением., @Khalid Abu-Khadija

Спасибо за ваш ответ на майскую проблему, @Khalid Abu-Khadija