#1 2023-03-17 11:56:26

B21
Учасник
Зареєстрований: 2022-12-28
Повідомлень: 6

Як правильно перервати цикл?

Всім привіт, підкажіть, як правильно перервати цикл.
Принцип роботи коду:
Натискаєш кнопку – вмикається реле – після спрацьовування датчика холу – вимикається реле, кнопка весь цей час натиснута – відпускаєш кнопку – нічого не відбувається – далі натискаєш і все по колу.
Без циклу while(true) - реле вмикається натисканням кнопки ,
з циклом - на реле злегка спалахує лампочка включення і все.
Як правильно зробити переривання?

int hollPin = 6;
int MotorPin = 4;
int PrivodPin = 2; 
int FlagOld = 0;
int FlagNew = 0;


void setup() {
  Serial.begin(9600);
  pinMode(MotorPin, OUTPUT);
  digitalWrite(MotorPin, HIGH);
  pinMode(PrivodPin, INPUT);
  digitalWrite(PrivodPin, LOW);
  pinMode(hollPin, INPUT);
  
}
void loop() {
 FlagNew = digitalRead(PrivodPin);
  if (FlagOld != FlagNew && FlagNew == 1) {
    digitalWrite(MotorPin, LOW);    
    unsigned long currentTime = millis();    
    unsigned long startTime = millis();
    while(true){
        if (digitalRead(hollPin) == HIGH || (currentTime == startTime + 3000)) {
      break;
      } 
    }

  digitalWrite(MotorPin, HIGH);
  FlagOld = FlagNew;
  }
  else if (FlagOld != FlagNew)
    FlagOld = FlagNew;
  }

Неактивний

#2 2023-03-17 14:19:08

Roman1984
Учасник
Зареєстрований: 2017-02-17
Повідомлень: 97

Re: Як правильно перервати цикл?

Обратите внимание, что внутри цикла while(true) переменная currentTime и переменная startTime уже не зависят от millis() и как следствие не меняются.

Неактивний

#3 2023-03-17 19:15:55

B21
Учасник
Зареєстрований: 2022-12-28
Повідомлень: 6

Re: Як правильно перервати цикл?

Roman1984 пише:

Обратите внимание, что внутри цикла while(true) переменная currentTime и переменная startTime уже не зависят от millis() и как следствие не меняются.

int hollPin = 6;
int MotorPin = 4;
int PrivodPin = 2; 
int FlagOld = 0;
int FlagNew = 0;

unsigned long currentTime;    
unsigned long startTime;

void setup() {
  Serial.begin(9600);
  pinMode(MotorPin, OUTPUT);
  digitalWrite(MotorPin, HIGH);
  pinMode(PrivodPin, INPUT);
  digitalWrite(PrivodPin, LOW);
  pinMode(hollPin, INPUT);
  currentTime = millis();       
  startTime = currentTime;  
  
}
void loop() {
 FlagNew = digitalRead(PrivodPin);
  if (FlagOld != FlagNew && FlagNew == 1) {
    digitalWrite(MotorPin, LOW);    
    while(true){
        currentTime = millis(); 
        if (digitalRead(hollPin) == HIGH || (currentTime == startTime + 3000)) {
      break;
      } 
    }

  digitalWrite(MotorPin, HIGH);
  FlagOld = FlagNew;
  }
  else if (FlagOld != FlagNew)
    FlagOld = FlagNew;
  }

Немного изменил переменные но реле все равно не включается...

В моей предыдущей версии кода реле работало но не было того самого цикла который прерывал работу реле после срабатывания датчика холла. Собственно вместо

delay(2000);

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

//рабочая версия без цикла
FlagNew = digitalRead(PrivodPin);
  if (FlagOld != FlagNew && FlagNew == 1) {
    digitalWrite(MotorPin, LOW);
    delay(2000);
    digitalWrite(MotorPin, HIGH);
    FlagOld = FlagNew;
    Serial.println(FlagNew);
  }
  else if (FlagOld != FlagNew)
    FlagOld = FlagNew;

Неактивний

#4 2023-03-17 20:59:46

г0cть
Гість

Re: Як правильно перервати цикл?

Если правильно понял алгоритм, то как-то так

int hollPin = 6;
int MotorPin = 4;
int PrivodPin = 2;
bool flag = 0;

void setup() {
  Serial.begin(9600);
  pinMode(MotorPin, OUTPUT);
  digitalWrite(MotorPin, HIGH);
  pinMode(PrivodPin, INPUT);
  pinMode(hollPin, INPUT);

}
void loop() {

  if (digitalRead(PrivodPin) && !flag) {
    digitalWrite(MotorPin, LOW);
    flag = 1;
  }
  if (digitalRead(hollPin) && flag) digitalWrite(MotorPin, HIGH);

  if (!digitalRead(PrivodPin) && flag)flag = 0;

}

#5 2023-03-17 23:40:41

B21
Учасник
Зареєстрований: 2022-12-28
Повідомлень: 6

Re: Як правильно перервати цикл?

г0cть пише:

Если правильно понял алгоритм, то как-то так

int hollPin = 6;
int MotorPin = 4;
int PrivodPin = 2;
bool flag = 0;

void setup() {
  Serial.begin(9600);
  pinMode(MotorPin, OUTPUT);
  digitalWrite(MotorPin, HIGH);
  pinMode(PrivodPin, INPUT);
  pinMode(hollPin, INPUT);

}
void loop() {

  if (digitalRead(PrivodPin) && !flag) {
    digitalWrite(MotorPin, LOW);
    flag = 1;
  }
  if (digitalRead(hollPin) && flag) digitalWrite(MotorPin, HIGH);

  if (!digitalRead(PrivodPin) && flag)flag = 0;

}

Снова не сработало реле, почему то светодиод промигивает на 20% яркости и все - такое ощущение что контакт плохой, НО когда заливаешь предыдущий скетч без while - светодиод загорается на полную и реле работает как надо.
Если бы был плохой контакт - никакой бы скетч не заработал, а так даже через setup включаешь, 5 сек и выключаешь - все работает.
Вот схема подключения
sxem1.png

Неактивний

#6 2023-03-18 00:24:33

akapulko
Гість

Re: Як правильно перервати цикл?

Приберіть резистори 10к, замініть дротами і  спробуйте цей код:

void setup() {
  PORTD |= _BV(PD2) | _BV(PD6); // Internal pull-ups on PD2, PD6
  EICRA = _BV(ISC01); // The falling edge of INT0 generates an interrupt request
  EIMSK = _BV(INT0); // Enable INT0
  PCICR |= _BV(PCIE2); // Enable PORTD PCI
  PCMSK2 |= _BV(PCINT22); // Select PCINT22 PD7
  sei();
}

void loop() {}

ISR(INT0_vect) {
  PORTD |= _BV(PD4); // Relay on
  EIFR |= _BV(INTF0); // Clear interrupt flag
}

ISR(PCINT2_vect) {
  PORTD &= ~_BV(PD4); // Relay off
}

#7 2023-03-18 00:27:07

akapulko
Гість

Re: Як правильно перервати цикл?

Забув, додайте першим рядком в setup()-і:

DDRD |= _BV(PD4);

#8 2023-03-18 00:53:17

akapulko
Гість

Re: Як правильно перервати цикл?

Заплутав сам себе: Просто приберіть резистори 10к, замініть дротами. Дроти замість резисторів під'єднувати не потрібно.

#9 2023-03-18 10:52:37

г0cть
Гість

Re: Як правильно перервати цикл?

B21 пише:

Снова не сработало реле

Вот схема подключения

С такой схемой и не будет. Код не соответствует схеме. По схеме кнопка замыкается на землю, у вас в коде (и соотв. у меня) на +. Что за датчик? Когда он срабатывает приходит + или 0?

int hollPin = 6;
int MotorPin = 4;
int PrivodPin = 2;
bool flag = 0;

void setup() {
  Serial.begin(9600);
  pinMode(MotorPin, OUTPUT);
  digitalWrite(MotorPin, HIGH);
  pinMode(PrivodPin, INPUT_PULLUP);
  pinMode(hollPin, INPUT_PULLUP);

}
void loop() {

  if (!digitalRead(PrivodPin) && !flag) {
    digitalWrite(MotorPin, LOW);
    flag = 1;
  }
  if (!digitalRead(hollPin) && flag) digitalWrite(MotorPin, HIGH);

  if (digitalRead(PrivodPin) && flag)flag = 0;

}

на схеме в симуляторе: переключатель - кнопка, кнопка -датчик
https://wokwi.com/projects/359522045614208001

з/ы ну и дребезг никто не отменял  smile

#10 2023-03-18 22:49:56

B21
Учасник
Зареєстрований: 2022-12-28
Повідомлень: 6

Re: Як правильно перервати цикл?

г0cть пише:
B21 пише:

Снова не сработало реле

Вот схема подключения

С такой схемой и не будет. Код не соответствует схеме. По схеме кнопка замыкается на землю, у вас в коде (и соотв. у меня) на +. Что за датчик? Когда он срабатывает приходит + или 0?

int hollPin = 6;
int MotorPin = 4;
int PrivodPin = 2;
bool flag = 0;

void setup() {
  Serial.begin(9600);
  pinMode(MotorPin, OUTPUT);
  digitalWrite(MotorPin, HIGH);
  pinMode(PrivodPin, INPUT_PULLUP);
  pinMode(hollPin, INPUT_PULLUP);

}
void loop() {

  if (!digitalRead(PrivodPin) && !flag) {
    digitalWrite(MotorPin, LOW);
    flag = 1;
  }
  if (!digitalRead(hollPin) && flag) digitalWrite(MotorPin, HIGH);

  if (digitalRead(PrivodPin) && flag)flag = 0;

}

на схеме в симуляторе: переключатель - кнопка, кнопка -датчик
https://wokwi.com/projects/359522045614208001

з/ы ну и дребезг никто не отменял  smile

Кароч походу датчик холла по одному месту пошел, поставил новый цифровой датчик A3144, при срабатывании приходит 0. Последняя версия твоего кода рабочая единственное что убрал PULLUPпы, резисторы оба оставил и добавил delay(10); после if (!digitalRead(PrivodPin) && !flag) {.
Моя версия кода тоже сработала, правда и в одной и другой версии +3000мс не сработали, то есть если датчик холла не сработает то мотор будет крутится бесконечно. 3 сек была тип защита, или датчик или время, и получается что датчик холла отключается только тогда когда замкнута кнопка, а если вдруг кнопка отожмется назад то датчик холла не сработает и будет ждать сначала нажатую кнопку а потом сработает...
А так всем огромное спасибо за помощь)

Неактивний

#11 2023-03-18 23:08:30

г0cть
Гість

Re: Як правильно перервати цикл?

B21 пише:

+3000мс не сработали, то есть если датчик холла не сработает то мотор будет крутится бесконечно. 3 сек была тип защита,

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

#12 2023-03-19 14:23:25

гоcть
Гість

Re: Як правильно перервати цикл?

Внимание вопрос: Что будет, если нажать на кнопку, когда датчик Холла стоит на магните?  lol

#13 2023-03-19 15:01:22

chatGPT
Гість

Re: Як правильно перервати цикл?

гоcть пише:

Внимание вопрос: Что будет, если нажать на кнопку, когда датчик Холла стоит на магните?  lol

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

Однако, если кнопка связана с датчиком Холла и предназначена для работы с ним, то результаты могут зависеть от конкретной конфигурации и настроек системы.

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

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

#14 2023-03-19 19:30:07

akapulko
Гість

Re: Як правильно перервати цикл?

гоcть пише:

Внимание вопрос: Что будет, если нажать на кнопку, когда датчик Холла стоит на магните?  lol

Якщо обробляти сигнал за допомогою PinChangeInterrupt (див. приклад коду вище), все буде ок, реле вимкнеться як тільки магніт віддалиться від датчика!

#15 2023-03-19 23:00:07

B21
Учасник
Зареєстрований: 2022-12-28
Повідомлень: 6

Re: Як правильно перервати цикл?

гоcть пише:

Внимание вопрос: Что будет, если нажать на кнопку, когда датчик Холла стоит на магните?  lol

Магнит никогда не станет на датчике холла, даже после срабатывания датчика холла моторчик по инерции проворачивает магнит за его пределы, нереально что бы мотор остановил магнит напротив датчика, ну а что бы перестраховаться можно после срабатывания датчика добавить задержку 0.2 - 0.4сек, но тогда мотор стартовать будет с другой точки.

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму