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

ruri

✩✩✩✩✩✩✩
4 Апр 2026
6
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
685
107
Нет. </> так правильно кода оформление. Есть ли в нём ошибки укажут знатоки.

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
6
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 строк всё сделал.
я тут недавно. ткните носом как паравильно
 

ruri

✩✩✩✩✩✩✩
4 Апр 2026
6
0
мы, видимо, в разных средах пишем. поэтому и оформление разное
 

Мишутк

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

bort707

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

ruri

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

Вложения

Мишутк

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

bort707

★★★★★★✩
21 Сен 2020
3,455
993
там много намешано.
О чем вы? - скетч всего 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,455
993
Что касается ошибки, согласен с @Мишутк,

@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
6
0
Спасибо!!! Понял.
Знаний действительно не хватает. Учебник читаю...
Просто обкатывал этот фрагмент отдельно как скетч - всё работало. Только сделал функцией - перестало (понял почему).
Действительно проще сделать ссылками. Мне они нужны будут в дальнейшем.