Проблема кода в loop компиляции на Arduino Nano

TigtonKosh
Offline
Зарегистрирован: 17.04.2018

Помогите пожалуйста
Я не понимаю, что от меня требует программа.
Калибровку провел, сменил с 1 на 0, вновь сделал прошивку и выдает:

Скрин по ссылке
https://imgur.com/a/zCQjo

Клапауций 555
Offline
Зарегистрирован: 10.03.2018

хочет, что бы ты научился не только картинко по помойкам постить, а и копировать текст в тело поста.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что, код вставить сюда не судьба? Впредь и смотреть не буду.

Та фигурная скобка, в которую Вас тычут носом - не закрыта. Считайте скобки. Плохо, видать, калибровку провели.

TigtonKosh
Offline
Зарегистрирован: 17.04.2018
Ошибка:
C:\Users\...\GyverMOD_v._1.2.9_DISP.ino: In function 'void loop()':
 
GyverMOD_v._1.2.9_DISP:409:11: error: 'chang' was not declared in this scope
 
     }      if (change_v_flag) {
 
           ^
 
GyverMOD_v._1.2.9_DISP:409:11: error: expected ')' at end of input
 
GyverMOD_v._1.2.9_DISP:409:11: error: expected statement at end of input
 
GyverMOD_v._1.2.9_DISP:409:11: error: expected '}' at end of input
 
GyverMOD_v._1.2.9_DISP:409:11: error: expected '}' at end of input
 
exit status 1
'chang' was not declared in this scope

Код (при ошибке обозначается красным строка 394): 

//-----------------------------------НАСТРОЙКИ------------------------------------
#define initial_calibration 0  // калибровка вольтметра 1 - включить, 0 - выключить
#define welcome 0              // приветствие (слова GYVER VAPE при включении), 1 - включить, 0 - выключить
#define battery_info 1         // отображение напряжения аккумулятора при запуске, 1 - включить, 0 - выключить
#define sleep_timer 60         // таймер сна в секундах
#define vape_threshold 7       // отсечка затяжки, в секундах
#define turbo_mode 0           // турбо режим 1 - включить, 0 - выключить
#define battery_percent 0      // отображать заряд в процентах, 1 - включить, 0 - выключить
#define battery_low 2.8        // нижний порог срабатывания защиты от переразрядки аккумулятора, в Вольтах!
//-----------------------------------НАСТРОЙКИ------------------------------------

#include <EEPROMex.h>   // библиотека для работы со внутренней памятью ардуино
#include <LowPower.h>   // библиотека сна

//-----------кнопки-----------
#define butt_up 5      // кнопка вверх
#define butt_down 4    // кнпока вниз
#define butt_set 3     // кнопка выбора
#define butt_vape 2    // кнопка "парить"
//-----------кнопки-----------

//-----------флажки-----------
boolean up_state, down_state, set_state, vape_state;
boolean up_flag, down_flag, set_flag, set_flag_hold, set_hold, vape_btt, vape_btt_f;
volatile boolean wake_up_flag, vape_flag;
boolean change_v_flag, change_w_flag, change_o_flag;
volatile byte mode, mode_flag = 1;
boolean flag;          // флаг, разрешающий подать ток на койл (защита от КЗ, обрыва, разрядки)
//-----------флажки-----------

//-----------пины-------------
#define mosfet 10      // пин мосфета (нагрев спирали)
#define battery 5      // пин измерения напряжения акума
//-----------пины-------------

//-----------дисплей-----------
#include <TimerOne.h>
#include <TM74HC595Display.h>
#define disp_vcc 13
#define SCLK 6
#define RCLK 7
#define DIO 8
TM74HC595Display disp(SCLK, RCLK, DIO);
unsigned char SYM[47];
//-----------дисплей-----------

int bat_vol, bat_volt_f;   // хранит напряжение на акуме
int PWM, PWM_f;           // хранит PWM сигнал

//-------переменные и коэффициенты для фильтра-------
int bat_old, PWM_old = 800;
float filter_k = 0.04;
float PWM_filter_k = 0.1;
//-------переменные и коэффициенты для фильтра-------

unsigned long last_time, vape_press, set_press, last_vape, wake_timer; // таймеры
int volts, watts;    // храним вольты и ватты
float ohms;          // храним омы
float my_vcc_const;  // константа вольтметра
volatile byte vape_mode, vape_release_count;

//---------------надписи---------------
byte VVOL[4] = {41, 36, 32, 30};
byte VAVA[4] = {41, 36, 20, 42};
byte COIL[4] = {22, 32, 28, 30};

byte GYVE[4] = {26, 37, 36, 24};
byte YVEA[4] = {37, 36, 24, 20};
byte VAPE[4] = {36, 20, 33, 24};
byte BVOL[4] = {44, 36, 32, 30};
byte vape1[4] = {46, 45, 46, 45};
byte vape2[4] = {45, 46, 45, 46};
byte LOWB[4] = {8, 45, 45, 0};
byte BYE[4] = {21, 37, 24, 42};
byte BLANK[4] = {42, 42, 42, 42};
byte V[4] = {36, 42, 42, 42};
byte A[4] = {36, 20, 42, 42};
byte P[4] = {36, 20, 33, 42};
byte E[4] = {36, 20, 33, 24};
//----------------надписи---------------

void setup() {
  Serial.begin(9600);
  if (initial_calibration) calibration();  // калибровка, если разрешена

  //----читаем из памяти-----
  volts = EEPROM.readInt(0);
  watts = EEPROM.readInt(2);
  ohms = EEPROM.readFloat(4);
  my_vcc_const = EEPROM.readFloat(8);
  //----читаем из памяти-----

  symbols(); // инициализировать символы для дисплея
  Timer1.initialize(1500);          // таймер
  Timer1.attachInterrupt(timerIsr);

  //---настройка кнопок и выходов-----
  pinMode(butt_up , INPUT_PULLUP);
  pinMode(butt_down , INPUT_PULLUP);
  pinMode(butt_set , INPUT_PULLUP);
  pinMode(butt_vape , INPUT_PULLUP);
  pinMode(mosfet , OUTPUT);
  pinMode(disp_vcc , OUTPUT);
  digitalWrite(disp_vcc, HIGH);
  Timer1.disablePwm(mosfet);    // принудительно отключить койл
  digitalWrite(mosfet, LOW);    // принудительно отключить койл
  //---настройка кнопок и выходов-----

  //------приветствие-----
  if (welcome) {
    disp_send(GYVE);
    delay(400);
    disp_send(YVEA);
    delay(400);
    disp_send(VAPE);
    delay(400);
  }
  //------приветствие-----

  // измерить напряжение аккумулятора
  bat_vol = readVcc();
  bat_old = bat_vol;

  // проверка заряда акума, если разряжен то прекратить работу
  if (bat_vol < battery_low * 1000) {
    flag = 0;
    disp.clear();
    disp_send(LOWB);
    Timer1.disablePwm(mosfet);    // принудительно отключить койл
    digitalWrite(mosfet, LOW);    // принудительно отключить койл
  } else {
    flag = 1;
  }

  if (battery_info) {  // отобразить заряд аккумулятора при первом включении
    disp.clear();
    disp_send(BVOL);
    delay(500);
    disp.float_dot((float)bat_vol / 1000, 2);
    delay(1000);
    disp.clear();
  }
}

void loop() {
  if (millis() - last_time > 50) {                       // 20 раз в секунду измеряем напряжение
    last_time = millis();
    bat_vol = readVcc();                                 // измерить напряжение аккумулятора в миллиВольтах
    bat_volt_f = filter_k * bat_vol + (1 - filter_k) * bat_old;  // фильтруем
    bat_old = bat_volt_f;                                // фильтруем
    if (bat_volt_f < battery_low * 1000) {               // если напряжение меньше минимального
      flag = 0;                                          // прекратить работу
      disp.clear();
      disp_send(LOWB);
      Timer1.disablePwm(mosfet);    // принудительно отключить койл
      digitalWrite(mosfet, LOW);    // принудительно отключить койл
    }
  }

  //-----------опрос кнопок-----------
  up_state = !digitalRead(butt_up);
  down_state = !digitalRead(butt_down);
  set_state = !digitalRead(butt_set);
  vape_state = !digitalRead(butt_vape);

  // если нажата любая кнопка, "продлить" таймер ухода в сон
  if (up_state || down_state || set_state || vape_state) wake_timer = millis();
  //-----------опрос кнопок-----------

  // service_mode();  // раскомментировать для отладки кнопок
  // показывает, какие кнопки нажаты или отпущены
  // использовать для проерки правильности подключения

  //---------------------отработка нажатия SET и изменение режимов---------------------
  if (flag) {                              // если акум заряжен
    if (set_state && !set_hold) {          // если кнпока нажата
      set_hold = 1;
      set_press = millis();                // начинаем отсчёт
      while (millis() - set_press < 300) {
        if (digitalRead(butt_set)) {       // если кнопка отпущена до 300 мс
          set_hold = 0;
          set_flag = 1;
          break;
        }
      }
    }
    if (set_hold && set_state) {           // если кнопка всё ещё удерживается
      if (!set_flag_hold) {
        disp.clear();
        set_flag_hold = 1;
      }
      if (round(millis() / 150) % 2 == 0) {
        if (!battery_percent) {
          disp.float_dot((float)bat_volt_f / 1000, 2); // показать заряд акума в вольтах
        } else {
          disp.digit4(map(bat_volt_f, battery_low * 1000, 4200, 0, 99)); // показать заряд акума в процентах
        }
      }
    }
    if (set_hold && !set_state && set_flag_hold) {  // если удерживалась и была отпущена
      set_hold = 0;
      set_flag_hold = 0;
      mode_flag = 1;
    }

    if (!set_state && set_flag) {  // если нажали-отпустили
      set_hold = 0;
      set_flag = 0;
      mode++;                      // сменить режим
      mode_flag = 1;
      if (mode > 2) mode = 0;      // ограничение на 3 режима
    }
    // ----------------------отработка нажатия SET и изменение режимов---------------------------

    // ------------------режим ВАРИВОЛЬТ-------------------
    if (mode == 0 && !vape_state && !set_hold) {
      if (mode_flag) {                     // приветствие
        mode_flag = 0;
        disp_send(VVOL);
        delay(400);
        disp.clear();
      }
      //---------кнопка ВВЕРХ--------
      if (up_state && !up_flag) {
        volts += 100;
        volts = min(volts, bat_volt_f);  // ограничение сверху на текущий заряд акума
        up_flag = 1;
        disp.clear();
      }
      if (!up_state && up_flag) {
        up_flag = 0;
        change_v_flag = 1;
      }
      //---------кнопка ВВЕРХ--------

      //---------кнопка ВНИЗ--------
      if (down_state && !down_flag) {
        volts -= 100;
        volts = max(volts, 0);
        down_flag = 1;
        disp.clear();
      }
      if (!down_state && down_flag) {
        down_flag = 0;
        change_v_flag = 1;
      }
      //---------кнопка ВНИЗ--------
      disp.float_dot((float)volts / 1000, 2); // отобразить на дисплее
    }
    // ------------------режим ВАРИВОЛЬТ-------------------


    // ------------------режим ВАРИВАТТ-------------------
    if (mode == 1 && !vape_state && !set_hold) {
      if (mode_flag) {                     // приветствие
        mode_flag = 0;
        disp_send(VAVA);
        delay(400);
        disp.clear();
      }
      //---------кнопка ВВЕРХ--------
      if (up_state && !up_flag) {
        watts += 1;
        byte maxW = (sq((float)bat_volt_f / 1000)) / ohms;
        watts = min(watts, maxW);               // ограничение сверху на текущий заряд акума и сопротивление
        up_flag = 1;
        disp.clear();
      }
      if (!up_state && up_flag) {
        up_flag = 0;
        change_w_flag = 1;
      }
      //---------кнопка ВВЕРХ--------

      //---------кнопка ВНИЗ--------
      if (down_state && !down_flag) {
        watts -= 1;
        watts = max(watts, 0);
        down_flag = 1;
        disp.clear();
      }
      if (!down_state && down_flag) {
        down_flag = 0;
        change_w_flag = 1;
      }
      //---------кнопка ВНИЗ--------
      disp.digit4(watts);        // отобразить на дисплее
    }
    // ------------------режим ВАРИВАТТ--------------

    // ----------режим установки сопротивления-----------
    if (mode == 2 && !vape_state && !set_hold) {
      if (mode_flag) {                     // приветствие
        mode_flag = 0;
        disp_send(COIL);
        delay(400);
        disp.clear();
      }
      //---------кнопка ВВЕРХ--------
      if (up_state && !up_flag) {
        ohms += 0.05;
        ohms = min(ohms, 3);
        up_flag = 1;
        disp.clear();
      }
      if (!up_state && up_flag) {
        up_flag = 0;
        change_o_flag = 1;
      }
      //---------кнопка ВВЕРХ--------

      //---------кнопка ВНИЗ--------
      if (down_state && !down_flag) {
        ohms -= 0.05;
        ohms = max(ohms, 0);
        down_flag = 1;
        disp.clear();
      }
      if (!down_state && down_flag) {
        down_flag = 0;
        change_o_flag = 1;
      }
      //---------кнопка ВНИЗ--------
      disp.float_dot(ohms, 2);        // отобразить на дисплее
    }
    // ----------режим установки сопротивления-----------

    //---------отработка нажатия кнопки парения-----------
    if (vape_state && flag && !wake_up_flag) {

      if (!vape_flag) {
        vape_flag = 1;
        vape_mode = 1;            // первичное нажатие
        delay(20);                // анти дребезг (сделал по-тупому, лень)
        vape_press = millis();    // первичное нажатие
      }

      if (vape_release_count == 1) {
        vape_mode = 2;               // двойное нажатие
        delay(20);                   // анти дребезг (сделал по-тупому, лень)
      }
      if (vape_release_count == 2) {
        vape_mode = 3;               // тройное нажатие
      }

      if (millis() - vape_press > vape_threshold * 1000) {  // "таймер затяжки"
        vape_mode = 0;
        digitalWrite(mosfet, 0);
      }

      if (vape_mode == 1) {                                           // обычный режим парения
        if (round(millis() / 150) % 2 == 0)
          disp_send(vape1); else disp_send(vape2);                    // мигать медленно
        if (mode == 0) {                                              // если ВАРИВОЛЬТ
          PWM = (float)volts / bat_volt_f * 1024;                     // считаем значение для ШИМ сигнала
          if (PWM > 1023) PWM = 1023;                                 // ограничил PWM "по тупому", потому что constrain сука не работает!
          PWM_f = PWM_filter_k * PWM + (1 - PWM_filter_k) * PWM_old;  // фильтруем
          PWM_old = PWM_f;                                            // фильтруем
        }
        Timer1.pwm(mosfet, PWM_f);                                    // управление мосфетом
      }
      if (vape_mode == 2 && turbo_mode) {                             // турбо режим парения (если включен)
        if (round(millis() / 50) % 2 == 0)
          disp_send(vape1); else disp_send(vape2);                    // мигать быстро
        digitalWrite(mosfet, 1);                                      // херачить на полную мощность
      }
      if (vape_mode == 3) {                                           // тройное нажатие
        vape_release_count = 0;
        vape_mode = 1;
        vape_flag = 0;
        good_night();    // вызвать функцию сна
      }
      vape_btt = 1;
    }

    if (!vape_state && vape_btt) {  // если кнопка ПАРИТЬ отпущена
      if (millis() - vape_press > 180) {
        vape_release_count = 0;
        vape_mode = 0;
        vape_flag = 0;
      }
      vape_btt = 0;
      if (vape_mode == 1) {
        vape_release_count = 1;
        vape_press = millis();
      }
      if (vape_mode == 2) vape_release_count = 2;

      digitalWrite(mosfet, 0);
      disp.clear();
      mode_flag = 0;

      // если есть изменения в настройках, записать в память
      if (change_v_flag) {
        EEPROM.writeInt(0, volts);
        change_v_flag = 0;
      }
      if (change_w_flag) {
        EEPROM.writeInt(2, watts);
        change_w_flag = 0;
      }
      if (change_o_flag) {
        EEPROM.writeFloat(4, ohms);
        change_o_flag = 0;
      }
      // если есть изменения в настройках, записать в память
    }
    if (vape_state && !flag) { // если акум сел, а мы хотим подымить
      disp.clear();
      disp_send(LOWB);
      delay(1000);
      vape_flag = 1;
    }
    //---------отработка нажатия кнопки парения-----------
  }

  if (wake_up_flag) wake_puzzle();                   // вызвать функцию 5 нажатий для пробудки

  if (millis() - wake_timer > sleep_timer * 1000) {  // если кнопки не нажимались дольше чем sleep_timer секунд
    good_night();
  }
} // конец loop

//------функция, вызываемая при выходе из сна (прерывание)------
void wake_up() {
  digitalWrite(disp_vcc, HIGH);  // включить дисплей
  Timer1.disablePwm(mosfet);    // принудительно отключить койл
  digitalWrite(mosfet, LOW);    // принудительно отключить койл
  wake_timer = millis();         // запомнить время пробуждения
  wake_up_flag = 1;
  vape_release_count = 0;
  vape_mode = 0;
  vape_flag = 0;
  mode_flag = 1;
}
//------функция, вызываемая при выходе из сна (прерывание)------

//------функция 5 нажатий для полного пробуждения------
void wake_puzzle() {
  detachInterrupt(0);    // отключить прерывание
  vape_btt_f = 0;
  boolean wake_status = 0;
  byte click_count = 0;
  while (1) {
    vape_state = !digitalRead(butt_vape);

    if (vape_state && !vape_btt_f) {
      vape_btt_f = 1;
      click_count++;
      switch (click_count) {
        case 1: disp_send(V);
          break;
        case 2: disp_send(A);
          break;
        case 3: disp_send(P);
          break;
        case 4: disp_send(E);
          break;
      }
      if (click_count > 4) {               // если 5 нажатий сделаны за 3 секунды
        wake_status = 1;                   // флаг "проснуться"
        break;
      }
    }
    if (!vape_state && vape_btt_f) {
      vape_btt_f = 0;
      delay(70);
    }
    if (millis() - wake_timer > 3000) {    // если 5 нажатий не сделаны за 3 секунды
      wake_status = 0;                     // флаг "спать"
      break;
    }
  }
  if (wake_status) {
    wake_up_flag = 0;
    disp.clear();
    delay(100);
  } else {
    disp.clear();
    good_night();     // спать
  }
}
//------функция 5 нажатий для полного пробуждения------

//-------------функция ухода в сон----------------
void good_night() {
  disp_send(BYE);      // попрощаться
  delay(500);
  disp.clear();
  Timer1.disablePwm(mosfet);    // принудительно отключить койл
  digitalWrite(mosfet, LOW);    // принудительно отключить койл
  delay(50);

  // подать 0 на все пины питания дисплея
  digitalWrite(disp_vcc, LOW);

  delay(50);
  attachInterrupt(0, wake_up, FALLING);                   // подключить прерывание для пробуждения
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);    // спать. mode POWER_OFF, АЦП выкл
}
//-------------функция ухода в сон----------------

//----------режим теста кнопок----------
void service_mode() {
  if (set_state && !set_flag) {
    set_flag = 1;
    Serial.println("SET pressed");
  }
  if (!set_state && set_flag) {
    set_flag = 0;
    Serial.println("SET released");
  }
  if (up_state && !up_flag) {
    up_flag = 1;
    Serial.println("UP pressed");
  }
  if (!up_state && up_flag) {
    up_flag = 0;
    Serial.println("UP released");
  }
  if (down_state && !down_flag) {
    down_flag = 1;
    Serial.println("DOWN pressed");
  }
  if (!down_state && down_flag) {
    down_flag = 0;
    Serial.println("DOWN released");
  }
  if (vape_state && !vape_flag) {
    vape_flag = 1;
    Serial.println("VAPE pressed");
  }
  if (!vape_state && vape_flag) {
    vape_flag = 0;
    Serial.println("VAPE released");
  }
}
//----------режим теста кнопок----------

// функция вывода моих слов на дисплей
void disp_send(byte sym[]) {
  for (int i = 0; i < 4; i++) {
    disp.set(SYM[sym[i]], 3 - i);
  }
}

void timerIsr()  //нужно для дисплея
{
  disp.timerIsr();
}

// символы для дисплея
void symbols() {

  SYM[0] = 0xC0; //0
  SYM[1] = 0xF9; //1
  SYM[2] = 0xA4; //2
  SYM[3] = 0xB0; //3
  SYM[4] = 0x99; //4
  SYM[5] = 0x92; //5
  SYM[6] = 0x82; //6
  SYM[7] = 0xF8; //7
  SYM[8] = 0x80; //8
  SYM[9] = 0x90; //9

  SYM[10] = 0b01000000; //.0
  SYM[11] = 0b01111001; //.1
  SYM[12] = 0b00100100; //.2
  SYM[13] = 0b00110000; //.3
  SYM[14] = 0b00011001; //.4
  SYM[15] = 0b00010010; //.5
  SYM[16] = 0b00000010; //.6
  SYM[17] = 0b01111000; //.7
  SYM[18] = 0b00000000; //.8
  SYM[19] = 0b00010000; //.9

  SYM[20] = 0x88; //A
  SYM[21] = 0x83; //b
  SYM[22] = 0xC6; //C
  SYM[23] = 0xA1; //d
  SYM[24] = 0x86; //E
  SYM[25] = 0x8E; //F
  SYM[26] = 0xC2; //G
  SYM[27] = 0x89; //H
  SYM[28] = 0xF9; //I
  SYM[29] = 0xF1; //J
  SYM[30] = 0xC3; //L
  SYM[31] = 0xA9; //n
  SYM[32] = 0xC0; //O
  SYM[33] = 0x8C; //P
  SYM[34] = 0x98; //q
  SYM[35] = 0x92; //S
  SYM[36] = 0xC1; //U
  SYM[37] = 0x91; //Y
  SYM[38] = 0xFE; //hight -
  SYM[39] = 0b11110111; //low -
  SYM[40] = 0b01000001; //U.
  SYM[41] = 0b01100011; //u.
  SYM[42] = 0b11111111; //
  SYM[43] = 0b11100011; //u
  SYM[44] = 0b00000011; //b.
  SYM[45] = 0b10111111; //mid -
  SYM[46] = 0b11110110; //mid&high -
}

void calibration() {
  //--------калибровка----------
  for (byte i = 0; i < 7; i++) EEPROM.writeInt(i, 0);          // чистим EEPROM для своих нужд
  my_vcc_const = 1.1;
  Serial.print("Real VCC is: "); Serial.println(readVcc());     // общаемся с пользователем
  Serial.println("Write your VCC (in millivolts)");
  while (Serial.available() == 0); int Vcc = Serial.parseInt(); // напряжение от пользователя
  float real_const = (float)1.1 * Vcc / readVcc();              // расчёт константы
  Serial.print("New voltage constant: "); Serial.println(real_const, 3);
  EEPROM.writeFloat(8, real_const);                             // запись в EEPROM
  while (1); // уйти в бесконечный цикл
  //------конец калибровки-------
}

long readVcc() { //функция чтения внутреннего опорного напряжения, универсальная (для всех ардуин)
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
#else
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA, ADSC)); // measuring
  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH; // unlocks both
  long result = (high << 8) | low;

  result = my_vcc_const * 1023 * 1000 / result; // расчёт реального VCC
  return result; // возвращает VCC
}

 

TigtonKosh
Offline
Зарегистрирован: 17.04.2018

Проблема видимо была в том, что программа находилась не на диске C, поэтому жаловалась программа.