Форум программистов, компьютерный форум, киберфорум
Arduino
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.78/163: Рейтинг темы: голосов - 163, средняя оценка - 4.78
4 / 4 / 0
Регистрация: 05.01.2015
Сообщений: 33
1

Как выполнить код только 1 раз в цикле loop?

03.06.2019, 11:44. Показов 31676. Ответов 12

Author24 — интернет-сервис помощи студентам
Всем привет. Решил переделать автоматический освежитель воздуха. Идея такова, что после выключения света в туалете освежитель пшикает один раз и переходит в режим ожидания до следующего включения и выключения света. Для этого в схеме использовал фоторезистор и реле (потом заменю на транзистор), которое приводит в движение привод.

Так вот, я хочу, чтобы после выключения света, реле срабатывало только 1 раз (1 пшик), а затем переходило в режим ожидания.

Написал такой простенький код, однако после выключения света код в цикле loop не останавливается, реле, то включается, то выключается. Подскажите, пожалуйста, как реализовать эту затею? Спасибо!

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const int photo = A0;
const int motor = 13;
int raw = 0;
 
void setup() {
  pinMode( photo, INPUT );
  pinMode( motor, OUTPUT );
}
 
void loop() {
  raw = analogRead( photo );
  if( raw < 500)
    digitalWrite( motor, HIGH );
    delay(1000);
    digitalWrite( motor, LOW );
    delay(1000);
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.06.2019, 11:44
Ответы с готовыми решениями:

Как выполнить код только 1 раз?
всем привет, передо мной стоит такая задача: есть некий общий скрипт, состоящий из отдельных...

Как выполнить код только 1 раз и дальше ожидал
помогите с кодом! Иммется рация, хочу его руссифицировать произношение каналов и приветствия, ...

Как выполнить цикл loop определенное кол-во раз ?
как выполнить цикл loop определенное кол-во раз ? Вот Цикл :loop adb shell svc data enable adb...

Как выполнить код только один раз (при запуске программы?)
Как известно, At module level, you can use only comments and declarative statements. Значит, весь...

12
364 / 347 / 74
Регистрация: 18.03.2015
Сообщений: 1,292
03.06.2019, 12:05 2
Лучший ответ Сообщение было отмечено NeXan87 как решение

Решение

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const int photo = A0;
const int motor = 13;
int raw = 0;
int stat=1; 
 
void setup() {
  pinMode( photo, INPUT );
  pinMode( motor, OUTPUT );
}
 
void loop() {
  raw = analogRead( photo );
  if( raw < 500 && stat==1){
  stat=0;
    digitalWrite( motor, HIGH );
    delay(1000);
    digitalWrite( motor, LOW );
    delay(1000);
}
  if( raw >= 500)  stat=1;
}
3
4 / 4 / 0
Регистрация: 05.01.2015
Сообщений: 33
04.06.2019, 20:46  [ТС] 3
Спасибо большое! Все работает практически как надо. Вот только иногда случаются ложные срабатывания, все дело в отсутствии гистерезиса. Я думал, что проще всего в код, приведенный выше, добавить опрос фоторезистора не постоянно, а с задержкой, например, раз в 5 секунд. Delay не подходит, так как начинает тормозить другой код программы.

В интернете похожей реализации нигде не нашел (((
0
364 / 347 / 74
Регистрация: 18.03.2015
Сообщений: 1,292
05.06.2019, 09:56 4
Лучший ответ Сообщение было отмечено NeXan87 как решение

Решение

Для гистерезиса
строка 13
C++
1
  if( raw < 450 && stat==1){
строка 20
C++
1
if( raw >= 550)  stat=1;
или несколько опросов фоторезистора
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const int photo = A0;
const int motor = 13;
int raw = 0;
int stat = 0;
 
void setup() {
  pinMode( photo, INPUT );
  pinMode( motor, OUTPUT );
}
 
void loop() {
  raw = analogRead( photo );
  if ( raw < 500 && stat <= 32767) stat++; /* 32767 переполнение переменной int */ 
  if ( stat == 100) {  /* подобрать значение */
    stat ++;
    digitalWrite( motor, HIGH );
    delay(1000);
    digitalWrite( motor, LOW );
    delay(1000);
  }
  if ( raw >= 500)  stat = 0;
}
2
4 / 4 / 0
Регистрация: 05.01.2015
Сообщений: 33
06.06.2019, 22:28  [ТС] 5
Сергей 190 , огромное спасибо! Все работает! Остался последний и значимый штрих
Хотелось бы еще функцию срабатывания пшика по таймеру. То есть, в среднем на по-большому времени тратится около 5 минут, а по-маленькому около минуты. Поэтому, если свет был включен до 3 минут, не пшикать. Millis (), я как понимаю, не сбрасывает таймер, если он не дошел до заданного.
0
364 / 347 / 74
Регистрация: 18.03.2015
Сообщений: 1,292
08.06.2019, 13:18 6
Лучший ответ Сообщение было отмечено NeXan87 как решение

Решение

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const int photo = A0;
const int motor = 13;
int raw = 0;
int stat = 0;
unsigned long time;
 
void setup() {
  pinMode( photo, INPUT );
  pinMode( motor, OUTPUT );
}
 
void loop() {
  raw = analogRead( photo );
  if ( raw < 500 && stat == 0) {
    stat = 1;
    time = millis();
  }
  if ( stat == 1 && (millis() - time)>=180000) {  /* подобрать значение */
    stat =2;
    digitalWrite( motor, HIGH );
    delay(1000);
    digitalWrite( motor, LOW );
    delay(1000);
  }
  if ( raw >= 500)  stat = 0;
}
2
435 / 101 / 15
Регистрация: 21.02.2015
Сообщений: 845
13.06.2019, 11:13 7
NeXan87,
а как же две кнопки смыва,
это ли не сигнал о двух вариантах?
0
4 / 4 / 0
Регистрация: 05.01.2015
Сообщений: 33
13.06.2019, 11:20  [ТС] 8
Valakin, вы мне предлагаете установить концевик в бачке?)))
0
435 / 101 / 15
Регистрация: 21.02.2015
Сообщений: 845
13.06.2019, 11:36 9
NeXan87,
а что у вас за привод?
он бы тоже мог смывать от фоторезистора при времени меньше 3 минут))

на уровне выше сидящего человека можно поставить дальномер.
Он определяет садился ли человек,
если нет - смывает по маленькому))
мужики скажут спасибо)
0
4 / 4 / 0
Регистрация: 05.01.2015
Сообщений: 33
13.06.2019, 11:58  [ТС] 10
Я в домашних условиях тоже обычно сажусь, так как я не снайпер))) Вообще, вот полный код пшикалки, вдруг кто захочет повторить)

Принцип действия таков. На корпусе есть переключатель - OFF > MANUAL (только кнопка) > AUTO / MANUAL (кнопка и автоматика). В последнем режиме после включения света в туалете, запускается таймер готовности пшика (3 мин), до этого времени мигает синий светодиод (стоит RGB). Если прошло менее 3 минут и свет отключился (это время обычно затрачивается на коричневые дела), то после повторного включения он начинает идти заново. Но если прошло 3 минуты синий светодиод начинает гореть постоянно, это означает, что после выключения света произойдет распыление освежителя. Таймер можно сбросить нажатием кнопки, если пшикать не требуется, он остановится и запустится только после вык/вкл света.

Во время распыления (0,8 сек) включится зеленый светодиод и сменится мигающим красным, это блокировка повторного нажатия в течение 30 минут (запах освежителя обычно столько и держится). Также блокируется и кнопка ручного распыления.

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

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

Также присутствует защита от переразряда батареек (2 Ni-Mh последовательно). Если заряд опустится ниже 1,9В, то работа распылителя будет заблокирована полностью и включится красный светодиод, а Ардуино уйдет в сон для уменьшения энергопотребления.

Для понижения энергопотребления я понизил частоту до 64 кГц (в 256 раз), пришлось пересчитывать таймеры. А Ардуино запитал через повышающий DC-DC, так как максимальное напряжение батареек не хватает для нормальной работы. На выходе выставил 3.3 Вольт. Чем выше, тем больше ток потребления. При 5В - 40 мА (16Мгц), при 3.3В - 1.7 мА (64 кГц) в режиме ожидания.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
const int photo = A1;                   // фоторезистор
const int charge = A5;                  // вход 3В от батареек (защита от переразряда)
const int motor = 2;                    // привод распылителя
const int button = 3;                   // кнопка
const int led_block = 4;                // светодиод блокировки (красный)
const int auto_mode = 5;                // автоматический и ручный режимы
const int led_work = 6;                 // светодиод работы (зеленый)
const int led_on = 7 ;                  // светодиод готовности (синий)
const int buzzer = 8 ;                  // звуковой сигнал готовности
const int photoD = 9 ;                  // цифровой пин фоторезистора
float vout = 0.0;
float vin = 0.0;
float R1 = 7500;
float R2 = 1000;
int value = 0;                          // контроль батареек
int raw = 0;                            // переменная фоторезистора
int stlk = 1;                           // блокировка кнопки в течение 30 минут после срабатывания пшика по свету
int chrg = 1;                           // блокировка работы устройства с разряженными батарейками
int btn = 1;                            // блокировка нескольких пшиков при удержании кнопки
int led = 1;                            // индикация готовности пшика после выключения света
int pht = 1;                            // блокировака пшика по свету в течении 30 минут после нажатия на кнопку
int buzz = 1;                           // флаг пьезодинамика
int statblk = 1;                        // отключение счетчика stat
int buzzblk = 1;                        // блокировка пьезодинамика
int stoptimer = 1;                      // остановка таймера
uint32_t stat = 1;                      // управление шпиком
uint32_t svet = 0;                      // флаг управления готовности для пшика по свету
uint32_t cMs, pMs1, blokTime, buzzTime, autoTime;        // счетчики времени по свету
uint8_t Pshik = 0;                      // разрешение пшика после получения готовности
bool pshikBlock;                        // флаг блокировки повторного пшика
bool buzzBlock;                         // флаг блокировки пьезодинамика
bool autoReset;
int ledState = 0;                       // состояние светодиода
int32_t  previousMillis = 0;            // храним время последнего переключения светодиода
int32_t  interval = 3.9;               // интервал между включение/выключением светодиода ожидания (1 секунда)
 
#include <avr/power.h>
#include <avr/sleep.h>
 
void setup() {
  //Serial.begin(9600);
  clock_prescale_set(clock_div_256);     // понижение частоты работы микроконтроллера до 1 Мгц для экономии заряда батареек
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // устанавливаем интересующий нас спящий режим
  pinMode( photo, INPUT );
  pinMode( auto_mode, INPUT );
  pinMode( charge, INPUT );
  pinMode( motor, OUTPUT );
  pinMode( button, INPUT );
  pinMode( led_block, OUTPUT );
  pinMode( led_work, OUTPUT );
  pinMode( led_on, OUTPUT );
  pinMode( buzzer, OUTPUT );
  pinMode( photoD, INPUT );
  digitalWrite( motor, 0 );
  pshikBlock = false;
  buzzBlock = false;
  autoReset = true;
}
 
void loop() {
  cMs = millis();                                             // текущее время
  int buttonState = digitalRead( button );                    // считывание значения с пина кнопки
  int autoState = digitalRead( auto_mode );                   // считывание значения с пина ручного режима
  int photoState = digitalRead( photoD );
  raw = analogRead( photo );                                  // считывание значения с пина фоторезистора
  value = analogRead( charge );                               // считывание напряжения с пина (контроль заряда)
  vout = (value * 5.0) / 1024;                                // конвертор в понятные единицы измерения
  vin = vout / (R2 / (R1 + R2));
  //Serial.println(photoState);
 
  if (chrg == 1) {                                            // если заряд АКБ в норме
 
    if (stlk == 1 && btn == 1) {                              // управление светодиодом готовности
      if ( raw < 350 && vin <= 4.8 ) {                        // если в туалете темно
        digitalWrite( led_on, 0 );                            // выключаем светодиод разряда батареи
      } else if (led == 0 && btn == 1) {                      // если наступила готовность автоматического пшика
        digitalWrite( led_on, 1 );                            // светодиод готовности горит постоянно
      } else {
        if (cMs - previousMillis > interval) {                // сохраняем время последнего переключения
          previousMillis = cMs;
          if (ledState == 0)                                  // если светодиод не горит, то зажигаем, и наоборот
            ledState = 1;
          else
            ledState = 0;
          digitalWrite(led_on, ledState);                     // устанавливаем состояния выхода, чтобы включить или выключить светодиод
        }
      }
    }
 
    if ( stlk == 0 || btn == 0 ) {                            // управление светодиодом блокировки
      if ( raw < 350 && vin <= 4.8 ) {                        // если в туалете темно
        digitalWrite( led_block, 0 );                         // выключаем светодиод блокировки
      } else {                                                // если светло
        if (cMs - previousMillis > interval) {                // сохраняем время последнего переключения
          previousMillis = cMs;
          if (ledState == 0)                                  // если светодиод не горит, то зажигаем, и наоборот
            ledState = 1;
          else
            ledState = 0;
          digitalWrite(led_block, ledState);                  // устанавливаем состояния выхода, чтобы включить или выключить светодиод
        }
      }
    }
    if ( Pshik == 1 ) {                                       // если автоматическое срабатывание пшикалки разрешено
      if ( buttonState == 1 && btn == 1 ) {                   // после нажатия кнопки
        led = 1;                                              // отключить синий светодиод
        btn = 0;                                              // заблокировать кнопку
        stoptimer = 0;                                        // остановить таймер
        autoReset = true;                                     // запустить таймер блокировки повторного срабатывания на 30 минут
        autoTime = cMs;
      }
    } else {
      if ( buttonState == 1  && btn == 1 && stlk == 1 ) {        // если кнопка нажата и не заблокирована
        btn = 0;                                                // переключить флаг защиты повторных пшиков при удержании кнопки
        pht = 0;                                                // заблокировать пшик по свету на 30 минут
        buzzblk = 0;
        digitalWrite( led_on, 0 );                              // выключаем светодиод готовности
        digitalWrite( led_work, 1 );                            // включаем светодиод работы
        digitalWrite( motor, 1 );                               // включаем пшик
        delay(3);                                              // ждем 800 миллисекунд
        digitalWrite( motor, 0 );                               // выключаем пшик
        digitalWrite( led_work, 0 );                            // выключаем светодиод работы
        pshikBlock = true;                                      // запустить таймер блокировки повторного срабатывания на 30 минут
        blokTime = cMs;
      }
    }
 
    if ( autoState == 1 ) {                                   // если включен автометический и ручной режимы
      if ( cMs - pMs1 > 0.1 ) {                              // запускаем таймер отстчета готовности автоматического пшика
        pMs1 = cMs;                                           // время опроса фотореле каждые 1 секунду
        if ( raw > 450 ) {                                    // если в туалете светло
          svet++;                                             // запустить таймер
        } else {                                              // если темно
          svet = 0;                                           // обнулить таймер
        }
      }
      if ( svet == 660 && stoptimer == 1 ) {                  // если свет включен 3 минуты и более
        Pshik = 1;                                            // включаем флаг разрешения пшика
        led = 0;                                             // включаем постоянное свечение светодиода готовности
        buzz = 0;                                             // включить флаг пьезодинамика
        buzzBlock = true;
        buzzTime = pMs1;                                     // запустить таймер выключения пьезодинамика
      }
      if ( buzz == 0 && buzzblk == 1 ) {                     // если флаг пьезодинамика включен
        digitalWrite( buzzer, 1 );                           // включить пьезодинамик
      } else {                                              // или
        digitalWrite( buzzer, 0 );                           // выключить пьезодинамик
      }
      if ( raw < 350 ) {                                     // если в туалете темно
        stoptimer = 1;                                       // запустить таймер
      }
 
      if ( Pshik == 1 ) {                                     // если автоматическое срабатывание пшикалки разрешено
        if ( raw < 350 && stat <= 4294967295 && pht == 1 && statblk == 1 ) stat++;     // если свет выключился, все блокировки выключены, запустить таймер отсчета
        if ( stat == 15 ) {                                   // после пары секунд
          stat ++;
          digitalWrite( buzzer, 0 );
          digitalWrite( led_on, 0 );                          // выключаем светодиод готовности
          digitalWrite( led_work, 1 );                        // включаем светодиод работы
          digitalWrite( motor, 1 );                           // включаем привод
          delay(3);                                          // ждем 800 миллисекунд
          digitalWrite( motor, 0 );                           // выключаем привод
          digitalWrite( led_work, 0 );                        // выключаем светодиод работы
          stlk = 0;                                           // заблокировать кнопку на некоторое время
          statblk = 0;                                        // отключить таймер stat
          buzzblk = 0;
          pshikBlock = true;                                  // запустить таймер блокировки повторного срабатывания на 30 минут
          blokTime = cMs;
        }
      }
    }
  }
 
  if ( raw > 450 && cMs - blokTime > 7031 ) {                   // если в туалете светло и время блокировки вышло
    digitalWrite( led_block, 0 );                             // отключить светодиод блокировки
    stat = 1;                                                 // разблокировать таймер
    stlk = 1;                                                 // разблокировать кнопку
    pht = 1;                                                  // разблокировать автоматический пшик
    statblk = 1;
    buzzblk = 1;
  }
 
  if (pshikBlock)                                             // если блокировка активна
    if (cMs - blokTime > 7031) {
      stlk = 1;                                               // разблокировать таймер
      Pshik = 0;                                              // сбросить флаг готовности автоматического пшика
      svet = 0;                                               // сбросить таймер готовности
      led = 1;                                                // влючить мигание синим светодиодом
      pshikBlock = false;
    }
 
  if ( buttonState == 0 && cMs - blokTime > 7031 )  {           // если кнопка не нажата и время блокировки прошло
    btn = 1;                                                  // разблокировать повторное нажатие
    buzzblk = 1;                                              // отключить блокировку динамика
  }
 
  if (autoTime) {                                            
    if (cMs - autoTime > 3) {                                 // блокировка внопки после сброса таймера
      Pshik = 0;                                              // сбросить флаг готовности автоматического пшика
      svet = 0;                                               // сбросить таймер
      btn = 1;                                                // разблокировать кнопку
      autoTime = false;
    }
  }
 
  if (buzzBlock) {
    if (pMs1 - buzzTime > 0.1) {
      buzz = 1;                                               // включить динамик на 0,3 секунды
      buzzBlock = false;
    }
  }
 
    if ( vin <= 2.4 ) {                                         // и если заряд батареи слабый
      chrg = 0;                                                 // полностью блокируем работу устройства
      digitalWrite( led_on, 0 );                                // выключаем светодиод готовности
      digitalWrite( led_work, 0 );                              // выключаем светодиод работы
      digitalWrite( motor, 0 );                                 // включаем мотор
      digitalWrite( led_block, 1 );                             // включаем светодиод разряда батареи
      ADCSRA &= ~(1 << ADEN);                                   // Отключаем АЦП
      sleep_enable();
      sleep_mode();
      sleep_cpu ();                                             // Переводим МК в спящий режим
    }
 
}
2
0 / 0 / 0
Регистрация: 15.02.2020
Сообщений: 3
16.02.2020, 12:56 11
Здравствуйте! Спасибо за огромную проделанную работу. Помогите пожалуйста со схемой. Не могу понять"что и куда". Благодарю
0
управление сложностью
1693 / 1306 / 259
Регистрация: 22.03.2015
Сообщений: 7,545
Записей в блоге: 5
17.02.2020, 07:19 12
EnergY123, создайте отдельную тему, если у вас вопросы.
1
0 / 0 / 0
Регистрация: 15.02.2020
Сообщений: 3
18.02.2020, 07:44 13
NeXan87, Денис, здравствуйте. Помогите, пожалуйста, со схемой. Не могу разобраться. Спасибо большое
0
18.02.2020, 07:44
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.02.2020, 07:44
Помогаю со студенческими работами здесь

Как в цикле можно выполнить действие один раз?
Есть цикл, который выполняется n раз. Но 1 действие в этом цикле необходимо выполнить только 1...

Как в цикле выполнить определенное действие один раз?
for (int i = 0; i &lt; Notes.Count; i++) { if...

Как сделать что бы код работал каждый раз а не только один раз
&lt;div class=&quot;slider&quot;&gt; &lt;img src=&quot;g1.jpg&quot; class=&quot;g5&quot;&gt; &lt;img src=&quot;g2.jpg&quot; class=&quot;g55&quot;&gt; ...

Как в цикле выводить каждый раз только одну строку файла?
Есть какой то файл Input.txt и в нем есть данные int,string,int,int : 1,Иванов Иван...

Выполнить цикл замедления только один раз, как?
Приветствую всех. Я новичок в ардуино, освоил некоторые простые функции, но не могу понять как...

Как только один раз выполнить функцию в данном проекте?
(SFML)Нужно выполнить view.zoom(0.9f); при вызове fight, но перед самой функцией, а у меня...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru