Как я могу по-другому мигать светодиодом, когда нажимаю кнопку переключения? - PullRequest
0 голосов
/ 09 мая 2018

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

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

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 7;     // the number of the pushbutton pin
const int ledPin =  6;      // the number of the LED pin
// variables will change:
int buttonState = 0;  

// variable for reading the pushbutton status
void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
   Serial.begin(9600); 
}

void loop() {
   int x=0; 
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  Serial.print(x);
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH &&  x==0) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    delay(1000);
    digitalWrite(ledPin, LOW);
     delay(1000);
    Serial.print(x);
  } else {
    // turn LED off:
    x = x+1;
  }
  if (buttonState == HIGH && x==1) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    delay(2000);
    digitalWrite(ledPin, LOW); 
    delay(2000);
     Serial.print(x);

  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
    x = x+1;
  }
  if (buttonState == HIGH && x==2) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    delay(3000);
    digitalWrite(ledPin, LOW);
    delay(3000);
     Serial.print(x);
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
    x = x+1;

  }
  if (buttonState == HIGH && x==3) {
    // turn LED off:
    digitalWrite(ledPin, LOW);
    x = 0;
  }
}

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

Ответы [ 4 ]

0 голосов
/ 09 мая 2018

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

Частота = 1 / Период

Период = Тонна + Тофф

6 Гц = 1000 миллис / Т => Т = 166 миллис

166 = Тон + Тофф (для рабочего цикла% 50 Тон = Тофф) => Тон = Тофф = 83 миллис

введите описание изображения здесь

const int ledPin = 13;
const int buttonPin = 2;
int state = -1;
bool willLightOn = false;

unsigned long currentDelay = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), changeState, FALLING);
}

void loop() {
  if(state % 3 == 0) { //6Hz 
    currentDelay = 83;
    willLightOn = true;
  } else if (state % 3 == 1) { //5Hz
    currentDelay = 100;
    willLightOn = true;
  } else if (state % 3 == 2) { //LED off
    currentDelay = 0;
    willLightOn = false;
    digitalWrite(ledPin, LOW);
  }

  currentMillis = millis();
    if (currentMillis - previousMillis >= currentDelay && willLightOn) {
        previousMillis = currentMillis;
        digitalWrite(ledPin, !digitalRead(ledPin));
    } 
}

void changeState() {
  state++;
}
0 голосов
/ 09 мая 2018

Прямо сейчас ваша логика проверяет 3 раза значение x в одном цикле. Код ниже включает свет всякий раз, когда x больше нуля. Значение x изменяется при нажатии кнопки.

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

if (x > 0)
{
    digitalWrite(ledPin, HIGH);
    delay(1000 * x);
    digitalWrite(ledPin, LOW);
}
if (buttonState == HIGH)
{
    x++;
    if (x > 3)
        x = 0;
}
0 голосов
/ 09 мая 2018

Ваш код не может работать:

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

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

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

Чтобы это работало, вы должны полностью изменить программу.

#define BLINK_SLEEP_TIME <some value> // insert value for 16.6666ms

//return 1 after a positive edge
bool button_read(void)
{
  static bool lastState=1; //set this to 1, so that a pressed button at startup does not trigger a instant reaction
  bool state = digitalRead(buttonPin);
  if(state != lastState)
    {
      state=lastState;
      return state;
    }
 return 0;
}

//Blink the LED with a given period, till button is pressed
//Times are in x*16.666ms or x/60Hz
//At least one time should be more than 0
void blink(uint8_t ontime, uint8_t offtime) 
{
  while(1)
  {
    for(uint8_t i=0;i<ontime;i++)
    {
      led_setOn();
      delay(BLINK_SLEEP_TIME);
      if(button_read())
      {
        return;
      }
    }
    for(uint8_t i=0;i<offtime;i++)
    {
      led_setOff();
      delay(BLINK_SLEEP_TIME);
      if(button_read())
      {
        return;
      }
    }
  }
}

const uint8_t time_table[][]=
{
  {0,50},//LED is off
  {6,6}, //LED blinks with 5Hz, 60Hz/2/6=5Hz
  {5,5}, //LED blinks with 6Hz, 60Hz/2/5=6Hz
}

void endless(void)
{
  uint8_t i=0;
  for(;;)
    {
      i++;
      if(i>2)
      {
        i=0;
      }
      blink(time_table[i][0],time_table[i][1]);
    }
}

Лучшим подходом будет использование аппаратного ШИМ-модуля и изменение значений после края на кнопке.

0 голосов
/ 09 мая 2018

Вы должны создать глобальное состояние приложения.Это состояние, где вы помните, если вы мигаете на частоте 50 Гц / 60 Гц / выкл.Тогда вы можете использовать переключатель, чтобы сделать правильную вещь.

Затем вы проверяете, нажата ли кнопка, и меняете состояние приложения.

См. Мой пример ниже:

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 7;     // the number of the pushbutton pin
const int ledPin =  6;      // the number of the LED pin
// variables will change:
int applicationState = 0;  
bool lightOn = true;

int currentDelay = 1000;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

// variable for reading the pushbutton status
void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}

void loop() {

    if (digitalRead(buttonPin) == HIGH) {
        applicationState++;
        if(applicationState >= 3) {
            applicationState = 0;
        }
        delay(100);
    }

    switch(applicationState){
        case 0:
            currentDelay = 1000;
            lightOn = true;
            break;
        case 1:
            currentDelay = 2000;
            lightOn = true;
            break;
        case 2:
            digitalWrite(ledPin, LOW);
            lightOn = false;
            break;
    }


    currentMillis = millis();
    if (currentMillis - previousMillis >= currentDelay && lightOn) {
        previousMillis = currentMillis;
        digitalWrite(ledPin, !digitalRead(ledPin));
    }      
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...