ARDUINO Странности поведения переменной при выходе из цикла

Статус
В этой теме нельзя размещать новые ответы.

ruri

✩✩✩✩✩✩✩
4 Апр 2026
5
0
Оформи код соответствующим тэгом, см. Правила
Добрый день.
Работаю с ARDUIN UNO, подключил "многофункциональный модуль" (4 семисегментных индикатора и три кнопки).
Вот кусок кода.

while (k2==1) //кнопка ВВОД
{
writeNumber(b1); //вывод цифры на индикатор
if (millis () - z >= 500) //цифры перебираются при удержании к1, поэтому задержка нужна
{
z= millis();
k1 = digitalRead(BTN_PIN1); //Кнопка перебора цифр
if (b1<=4) //переменная сохраняет выбранную цифру от 0 до 5
{if (k1==0) b1++;} //цифры перебираются циклично пока не нажмётся кнопка к2
else
{ (b1=0);}
}
k2 = digitalRead(BTN_PIN2); //чтение кнопки 2 ВВОД
Serial.println(b1); //вывод в монитор порта
}
Serial.println(b1); //повторный вывод

При переборе b1 выводится и в монитор и на индикатор правильной цифрой, а при нажатии к2 и выходе из whele - b2 выводится в монитор порта квадратиками.
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
709
108
Нет. </> так правильно кода оформление. Есть ли в нём ошибки укажут знатоки.

C++:
while (k2==1)
{
writeNumber(b1, b2, b3); //вывод цыфры на индикатор
if (millis () - z >= 500)
{
z= millis();
k1 = digitalRead(BTN_PIN1);
if (b1<=4)
{
if (k1==0) b1++;
}
else
{
(b1=0);
}
}
k2 = digitalRead(BTN_PIN2); //чтение кнопки 2 ВВОД
Serial.println(b1);
}
Serial.println(b1);
 
Изменено:

ruri

✩✩✩✩✩✩✩
4 Апр 2026
5
0
while (k2 == 1) {
writeNumber(b1, b2, b3); //вывод цифры на индикатор
if (millis() - z >= 500) {
z = millis();
k1 = digitalRead(BTN_PIN1);
if (b1 <= 4) {
if (k1 == 0) b1++;
} else {
(b1 = 0);
}
}
k2 = digitalRead(BTN_PIN2); //чтение кнопки 2 ВВОД
Serial.println(b1);
}
Serial.println(b1);

автоформатирование IDE вообще в 15 строк всё сделал.
я тут недавно. ткните носом как паравильно

мы, видимо, в разных средах пишем. поэтому и оформление разное
 

Мишутк

★✩✩✩✩✩✩
29 Мар 2025
96
42
мы, видимо, в разных средах пишем. поэтому и оформление разное
Ваш код должен компилироваться. По приведенному огрызку кода можно сделать кучу предположений. А компилирующийся пример можно вставить в WokWi и проверить. Ваш кусок - нельзя.
 

VictorArx

★★★✩✩✩✩
22 Мар 2021
709
108
@ruri, у вас часть кода. В какой симулятор это можно запихнуть?
 

bort707

★★★★★★★
21 Сен 2020
3,477
1,000
хм.. в приведённом фрагменте всего 16 строк
вот именно.
Вам намекают, что код надо показывать ПОЛНОСТЬЮ.
Не переоценивайте себя, вы не в состоянии указать, в какой части кода ошибка. Если бы вы это знали - сами бы нашли ее и исправили. А раз не знаете - показывайте всю программу, а не обрывок.
Как вообще можно говорить о выводе b2 куда-либо, если в приведенном отрывке этой переменной нет вовсе?
 
Изменено:

ruri

✩✩✩✩✩✩✩
4 Апр 2026
5
0
Ну там много намешано.
У меня он компилится и выполняется.
Но вот с переменными b1, b2, b3 какая-то ерунда
 

Вложения

Мишутк

★✩✩✩✩✩✩
29 Мар 2025
96
42
Но вот с переменными b1, b2, b3 какая-то ерунда
Не вчитываясь в код - у вас эти переменные объявлены глобально и в то же время используются локально в функции как аргументы. Происходит экранирование локальными глобальных. На этом можно прекратить разбор исходника и отправить вас устранять пробелы знаний как минимум по области видимости переменных, а также по передаче параметров по значению и по ссылке. Одновременно подкорректируйте свой стиль именования переменных, чтобы в дальнейшем избежать такой путаницы даже на уровне имен.
 

bort707

★★★★★★★
21 Сен 2020
3,477
1,000
там много намешано.
О чем вы? - скетч всего 145 строк
нафига вы его файлом выложили?

Для удобства пользователей выкладываю нормально:

C++:
#include <TimeLib.h>
#include <GTimer.h>
#include <DS1307RTC.h>
#include <Wire.h>

#define BTN_PIN1 0   //порт кнопка 1  перебора цифр
#define BTN_PIN2 1   //порт кнопка 2  сохранение цифры
#define BTN_PIN3 2   //порт кнопка 3  задание режима
#define ZUM_DIO 3    //порт зуммера
#define LATCH_DIO 4  // линия синхронизации данных, защелка (LCHCLK)
#define CLK_DIO 7    // линия тактирования (SFTCLK)
#define DATA_DIO 8   // линия передачи данных (SDI)


// коды цифр от 0 до 9
const byte seg_digits[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0X80, 0X90 };
// коды разрядов
const byte seg_num[] = { 0xF1, 0xF2, 0xF4, 0xF8 };
//кнопки
uint8_t k1 = 1;  // перебор цифр
uint8_t k2 = 1;  //ввод
uint8_t k3 = 1;  // смена данных выводить
//uint8_t a;
uint8_t a1;      // сколько
uint8_t a2;      // через сколько
uint8_t a3;      // во сколько
uint8_t b1 = 0;  // сколько
uint8_t b2 = 0;  // через сколько
uint8_t b3 = 0;  // во сколько
//uint8_t s=0;
static uint32_t z = millis();

void setup() {
  digitalWrite(ZUM_DIO, 1);
  Serial.begin(115200);
  //настройка выводов кнопок
  pinMode(BTN_PIN1, INPUT_PULLUP);
  pinMode(BTN_PIN2, INPUT_PULLUP);
  pinMode(BTN_PIN3, INPUT_PULLUP);
  // настройка контактов индикатора
  pinMode(LATCH_DIO, OUTPUT);
  pinMode(CLK_DIO, OUTPUT);
  pinMode(DATA_DIO, OUTPUT);
  pinMode(ZUM_DIO, OUTPUT);
}
// вывод цифры в заданный разряд
void writeNumber(uint8_t a1, uint8_t a2, uint8_t a3) {
  digitalWrite(LATCH_DIO, LOW);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_digits[a1]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_num[0]);
  digitalWrite(LATCH_DIO, HIGH);
  digitalWrite(LATCH_DIO, LOW);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_digits[a2]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_num[1]);
  digitalWrite(LATCH_DIO, HIGH);
  digitalWrite(LATCH_DIO, LOW);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_digits[a3 / 10]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_num[2]);
  digitalWrite(LATCH_DIO, HIGH);
  digitalWrite(LATCH_DIO, LOW);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_digits[a3 - ((a3 / 10) * 10)]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_num[3]);
  digitalWrite(LATCH_DIO, HIGH);
}
void set_poliv(uint8_t b1, uint8_t b2, uint8_t b3)
//if (s<2)
{
  //первый сегмент
  while (k2 == 1) {
    writeNumber(b1, b2, b3);  //вывод цифры на индикатор
    if (millis() - z >= 500) {
      z = millis();
      k1 = digitalRead(BTN_PIN1);
      if (b1 <= 4) {
        if (k1 == 0) b1++;
      } else {
        (b1 = 0);
      }
    }
    k2 = digitalRead(BTN_PIN2);  //чтение кнопки 2 ВВОД
    Serial.println(b1);
  }
  Serial.println(b1);
  //s++;
  digitalWrite(ZUM_DIO, 0);  //звуковой сигнал
  delay(100);
  digitalWrite(ZUM_DIO, 1);
  delay(300);

  //второй сегмент
  k2 = 1;
  while (k2 == 1) {
    writeNumber(b1, b2, b3);  //вывод цыфры на индикатор
    if (millis() - z >= 500) {
      z = millis();
      k1 = digitalRead(BTN_PIN1);
      if (b2 <= 4) {
        if (k1 == 0) b2++;
      } else {
        (b2 = 0);
      }
    }
    k2 = digitalRead(BTN_PIN2);  //чтение кнопки 2 ВВОД
    Serial.println(b2);
  }

  digitalWrite(ZUM_DIO, 0);
  delay(100);
  digitalWrite(ZUM_DIO, 1);
  delay(300);
  //третий сегмент
  k2 = 1;
  while (k2 == 1) {
    writeNumber(b1, b2, b3);  //вывод цыфры на индикатор
    if (millis() - z >= 500) {
      z = millis();
      k1 = digitalRead(BTN_PIN1);
      if (b3 <= 22) {
        if (k1 == 0) b3++;
      } else {
        (b3 = 0);
      }
    }
    k2 = digitalRead(BTN_PIN2);  //чтение кнопки 2 ВВОД
    Serial.println(b3);
  }
  // s++;
  digitalWrite(ZUM_DIO, 0);
  delay(100);
  digitalWrite(ZUM_DIO, 1);
  delay(300);
  //}
}
void loop() {
  Serial.println("начало");
  set_poliv(b1, b2, b3);
  k2 = 0;
  a1 = b1;
  a2 = b2;
  a3 = b3;
  writeNumber(a1, a2, a3);
  setSyncProvider(RTC.get);
  //Serial.println (hour());
  delay(5000);
}
 

bort707

★★★★★★★
21 Сен 2020
3,477
1,000
Что касается ошибки, согласен с @Мишутк,

@ruri, смотрите, переменные b1 b2 b3 в loop() и переменные b1 b2 b3 в
C++:
void set_poliv(uint8_t b1, uint8_t b2, uint8_t b3)
- это два совершенно разных набора переменных. Оттого, что вы присваиваете значение b2 внутри функции set_poliv() - значение b2 в loop() не меняется.

== исправление позже ==
На самом деле проблема (основная) вовсе не в области действия переменных, а в передаче b1 b2 b3 внутрь функции по значению. При таком вызове функции изменения, что происходят с аргументами внутри функции - не передается наружу. Для того чтобы изменения, произведенные над b1 b2 b3 внутри функции set_poliv, влияли на b1 b2 b3 в основной программе - их нужно передавать функции по ссылке
C++:
void set_poliv(uint8_t &b1, uint8_t &b2, uint8_t &b3)
После этого исправления то, что переменные b1-b3 обявлены и глобально, и локально - никак мешать не будет.

В целом, нужно отметить, что ТС не хвтает твердых знаний базовых понятий языка С/С++ и ему стоит начать с чтения хорошего толстого учебника
 
Изменено:

ruri

✩✩✩✩✩✩✩
4 Апр 2026
5
0
Спасибо!!! Понял.
Знаний действительно не хватает. Учебник читаю...
Просто обкатывал этот фрагмент отдельно как скетч - всё работало. Только сделал функцией - перестало (понял почему).
Действительно проще сделать ссылками. Мне они нужны будут в дальнейшем.
 

ruri

✩✩✩✩✩✩✩
4 Апр 2026
5
0
Добрый день.
Продолжается борьба с многофункциональным модулем.
Сейчас вообще какой-то полтергейст.
Есть функция ст. 69, в ней считывается состояние порта BTN_PIN3 2 9 ст. 85, 112, 135).
Функция вызывается два раза (ст. 158 и 171).
При первом вызове кнопка считывается правильно (1 - не нажата, 0 - нажата). а при втором вызове кнопка всегда считывается как 0 (нажата).
Не могу понять как так? Писал отдельный скетч на кнопку - всё прекрасно работает как и при первом вызове функции.

C++:
```cpp
#include <TimeLib.h>
#include <GTimer.h>
#include <DS1307RTC.h>
#include <Wire.h>

#define BTN_PIN1 0   //порт кнопка 1
#define BTN_PIN2 5   //порт кнопка 2
#define BTN_PIN3 2   //порт кнопка 3
#define LED1 2       //порт диода
#define ZUM_DIO 6    //порт зуммера
#define LATCH_DIO 4  // линия синхронизации данных, защелка (LCHCLK)
#define CLK_DIO 7    // линия тактирования (SFTCLK)
#define DATA_DIO 8   // линия передачи данных (SDI)


// коды цифр от 0 до 9
const byte seg_digits[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0X80, 0X90 };
// коды разрядов
const byte seg_num[] = { 0xF1, 0xF2, 0xF4, 0xF8 };
//кнопки


uint8_t k2 = 0;

uint8_t led1;
uint8_t a1 = 0;
uint8_t a2 = 0;
uint8_t a3 = 0;
uint8_t s = 0;


void setup() {

  Serial.begin(115200);
  //настройка выводов кнопок
  pinMode(BTN_PIN1, INPUT_PULLUP);
  pinMode(BTN_PIN2, INPUT_PULLUP);
  pinMode(BTN_PIN3, INPUT_PULLUP);
  // настройка контактов индикатора
  pinMode(LATCH_DIO, OUTPUT);
  pinMode(CLK_DIO, OUTPUT);
  pinMode(DATA_DIO, OUTPUT);
  pinMode(ZUM_DIO, OUTPUT);
  pinMode(LED1, OUTPUT);

  digitalWrite(ZUM_DIO, 1);
}
// вывод цифры в заданный разряд
void writeNumber(uint8_t a1, uint8_t a2, uint8_t a3) {
  digitalWrite(LATCH_DIO, LOW);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_digits[a1]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_num[0]);
  digitalWrite(LATCH_DIO, HIGH);
  digitalWrite(LATCH_DIO, LOW);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_digits[a2]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_num[1]);
  digitalWrite(LATCH_DIO, HIGH);
  digitalWrite(LATCH_DIO, LOW);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_digits[a3 / 10]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_num[2]);
  digitalWrite(LATCH_DIO, HIGH);
  digitalWrite(LATCH_DIO, LOW);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_digits[a3 - ((a3 / 10) * 10)]);
  shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, seg_num[3]);
  digitalWrite(LATCH_DIO, HIGH);
}

void set_cifr(uint8_t &a1, uint8_t &a2, uint8_t &a3) {
  uint32_t z = millis();
  uint8_t a = 0;
  uint8_t k1 = 1;
  uint8_t k3 = 1;
  //первый сегмент
  while (k3 == 1) {
    writeNumber(a1, a2, a3);  //вывод цыфры на индикатор
    if (millis() - z >= 500) {
      z = millis();
      k1 = digitalRead(BTN_PIN1);
      if (a <= 4) {
        if (k1 == 0) a++;
      } else a = 0;
    }
    a1 = a;
    k3 = digitalRead(BTN_PIN3);  //чтение кнопки 3 ВВОД
    Serial.print("1k3=");
    Serial.println(k3);
    delay(500);
  }
  a = 0;
  digitalWrite(ZUM_DIO, 0);  //звуковой сигнал
  delay(100);
  digitalWrite(ZUM_DIO, 1);
  delay(300);

  //второй сегмент
  k3 = 1;

  delay(500);

  while (k3 == 1) {
    writeNumber(a1, a2, a3);  //вывод цыфры на индикатор
    if (millis() - z >= 500) {
      z = millis();
      k1 = digitalRead(BTN_PIN1);
      if (a <= 4) {
        if (k1 == 0) a++;
      } else a = 0;

      a2 = a;
    }
    k3 = digitalRead(BTN_PIN3);  //чтение кнопки 3 ВВОД
    Serial.print("2k3=");
    Serial.println(k3);
  }
  a = 0;
  digitalWrite(ZUM_DIO, 0);
  delay(100);
  digitalWrite(ZUM_DIO, 1);
  delay(300);

  //третий сегмент
  k3 = 1;
  while (k3 == 1) {
    writeNumber(a1, a2, a3);  //вывод цыфры на индикатор
    if (millis() - z >= 500) {
      z = millis();
      k1 = digitalRead(BTN_PIN1);
      if (a <= 22) {
        if (k1 == 0) a++;
      } else a = 0;

      a3 = a;
    }
    k3 = digitalRead(BTN_PIN3);  //чтение кнопки 3 ВВОД
    Serial.print("3k3=");
    Serial.println(k3);
  }
  digitalWrite(ZUM_DIO, 0);
  delay(100);
  digitalWrite(ZUM_DIO, 1);
  delay(300);
}
void loop() {
  Serial.println("начало");
  digitalWrite(LED1, 1);
  if (s < 2) {
    k2 = digitalRead(BTN_PIN2);  //выбор режима
    //авто
    if (k2 == 0 && s == 0) {
      s++;

      digitalWrite(ZUM_DIO, 0);
      delay(100);
      digitalWrite(ZUM_DIO, 1);
      delay(300);
      Serial.println("авто");
      set_cifr(a1, a2, a3);
    }
    k2 = digitalRead(BTN_PIN2);

    //ручной
    if (k2 == 0 && s == 1) {
      Serial.println("ручной");
      s++;
      digitalWrite(ZUM_DIO, 0);
      delay(100);
      digitalWrite(ZUM_DIO, 1);
      delay(300);
      digitalWrite(LED1, 0);
      set_cifr(a1, a2, a3);
    }
    //высота
    //if (k2 == 0 && s == 2) {
    //  Serial.println("высота");
    //  s++;
    // digitalWrite(ZUM_DIO, 0);

    //  delay(100);
    //digitalWrite(ZUM_DIO, 1);
    //delay(300);
    //digitalWrite(LED1, 0);
    //set_cifr(a1, a2, a3);
    //}
  } else (s = 0);

  writeNumber(a1, a2, a3);
  //delay(500);
}

```
 
Статус
В этой теме нельзя размещать новые ответы.