Помогите с кодом :)

MaxiumTM
Offline
Зарегистрирован: 13.06.2016

База - Ардуино Нано в 3.0

Цель - сделать благое дело и реанимировать кухонную утварь.

Есть печка без мозгов. Стоит пылится. И тут мне пришла в голову гениальная мысль. А не оживить ли ее?! Почитав форумы - сделал выбор в пользу Ардуинки. После вкуривания Справочника языка по Ардуино родился у меня следующий код. 

////////////////////////////////////////////////////////
//Определение для часов реального времени ДС1307
#include <Arduino.h>
#include <Wire.h>         // this #include still required because the RTClib depends on it
#include "RTClib.h"

RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//////////////////////////////////////////////////////////
/* Define digital pins used to read the encoder */
#define DT 2
#define CLK 3
#define SW 4
int counter;          //переменная для присвоения значений
/////////////////////////////////////////////////////////////
//Другое разное
int n = 0;             //Счетчик цикла
byte minTimer = 0;     // Таймер работы духовки
////////////////////////////////////////////////////////////
//Подключения дисплея
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
////////////////////////////////////////////////////////////
//Порт и переменная и прочее для поучения значения темпиратуры и вычислений
byte analogPin = 0;     // номер порта к которому подключен потенциометр
int tempInput = 0;      // переменная для хранения считываемого значения темпиратуры
byte temp = 0;          //переменная для хранения заданного значения темпиратуры
/////////////////////////////////////////////////////////////
int hotterPin = 15;     // Светодиод, подключенный к вход/выходу 13 - ТЭН
int coollerPin = 4;     // Вентилятор выдува горячего воздуха из корпуса.
//////////////////////////////////////////////////////////////
byte timerBuffer = 0;   //Промежуточная переменная для вычисления
byte midiPin = 6;       //Пин звукового сигнала
/////////////////////////////////
void setup()
{
  lcd.begin(20, 4);     //объявление размеров дисплея (кол-во символов, кол-во строк)
  // Print a message to the LCD и установка курсора
  lcd.setCursor(1, 1);
  lcd.print("Hello :)");
  delay(5000);
  //Определение входов энкодера.
  pinMode(DT, INPUT);
  pinMode(CLK, INPUT);
  pinMode(SW, INPUT);
  digitalWrite(SW, HIGH);
  //Определение пина управления теном и вентилдятором, назначает режим работы - выход
  pinMode(hotterPin, OUTPUT);
  pinMode(coollerPin, OUTPUT);
  //Определение пина резонатора
  pinMode(midiPin, OUTPUT);
  //кусок от РТЦ.
  if (! rtc.begin())
  {
    lcd.print("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning())
  {
    lcd.print("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  //конец куска от РТЦ
}
/* Main program */
void loop()
{
  if (digitalRead(SW) != LOW) //Чтение нажатия кнопки энкодера
  {
    ++n; //Прибавление еденички к счетчику цикла
    while (n == 10000)  //вход в цикл измерения параметров, чтения и отображения времени. 1 раз в N оборото.
    {
      n = 0;
      tempInput = analogRead(analogPin);  //Чтение значения темпиратуры.  *******Нужно провести какие-то пересчеты промежуточные
      lcd.clear();
      lcd.setCursor(4, 0);
      if (minTimer > 0) //при выполнении условия духовка работает.
      {
        //Код работы духовки при значении таймера больше нуля.
        if (tempInput > temp)    //Проверка условия вкл/выкл ТЭНа.
        {
          digitalWrite(hotterPin, LOW);    // выключает тен духовки
        }
        else
        {
          digitalWrite(hotterPin, HIGH);    // включает тен духовки
        }
        DateTime now = rtc.now();    //Чтения текущего времени из РТЦ
        if (timerBuffer == (now.minute(), DEC))
        {
          // Нет никакого действия
        }
        else
        {
          minTimer = minTimer - 1;
          timerBuffer = (now.minute(), DEC);
          if (minTimer == 0)
            digitalWrite(hotterPin, LOW);  //Выключение ТЭНа
          for (int i = 0; i <= 30; i++)  //Время пищания 30 оборотов
          {
            digitalWrite(midiPin, HIGH);
            delay(400);
            digitalWrite(midiPin, LOW);
            delay(200);
            digitalWrite(midiPin, HIGH);
            delay(400);
            digitalWrite(midiPin, LOW);
            delay(1000);
          }
        }
      }//конец рабочего кода
      lcd.print("Time left:");
      lcd.print(minTimer);
      lcd.setCursor(2, 2);
      lcd.print("Temp:");
      lcd.print(tempInput); 
    }
    else //иначе идет индикация времени.
    {
      DateTime now = rtc.now();
      lcd.print(" (");
      lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
      lcd.print(") ");
      lcd.setCursor(6, 1);
      lcd.print(now.day(), DEC);
      lcd.print('/');
      lcd.print(now.month(), DEC);
      lcd.print("/");
      lcd.print(now.year(), DEC);
      lcd.setCursor(5, 3);
      lcd.print("Time:");
      lcd.print(now.hour(), DEC);
      lcd.print(':');
      lcd.print(now.minute(), DEC);
    }
    if (tempInput > 50)  //Проверка услови вкл/выкл вентилятора выдува из корпуса духовки
    {
      digitalWrite(coollerPin, HIGH);   // включает вентилятор на выдув из корпуса духовки
    }
    else
    {
      digitalWrite(coollerPin, LOW);    //выключает вентилятор на выдув из корпуса духовки
    }
  }  //конец цикла измерения параметров и отображения времени.
  else
  {
    goToMenu();
  }
} //Конец цикла всей программы
/*************************Обработка энкодера**************/
void encoder()
{
  byte DialPos;
  byte Last_DialPos;
  /* Read the status of the dial */
  DialPos = (digitalRead(CLK) << 1) | digitalRead(DT);
  /* Is the dial being turned anti-clockwise? */
  if (DialPos == 3 && Last_DialPos == 1)
  {
    counter--;
  }
  /* Is the dial being turned clockwise? */
  if (DialPos == 3 && Last_DialPos == 2)
  {
    counter++;
  }
  /* Save the state of the encoder */
  Last_DialPos = DialPos;
}
/**********************Menu*************************/
void goToMenu() //Переход есть. Расписать все красиво. Привязать к энкодеру.
{
  while (1)
  {
    byte var = 0;
    encoder();
    if ( counter > 6)
      counter = 1;
    var = counter;
    lcd.clear();
    lcd.print("Rotate the knob to select menu. Press the knob to select.");
    if (var == 1 && digitalRead(SW) = LOW)
    {
      menuOne();
    }
    else if (var == 2 && digitalRead(SW) = LOW)
    {
      menuTwo();
    }
    else if (var == 3 && digitalRead(SW) = LOW)
    {
      menuThree();
    }
    else if (var == 4 && digitalRead(SW) = LOW)
    {
      menuFour();
    }
    else if (var == 5 && digitalRead(SW) = LOW)
    {
      menuFive();
    }
    else if (var == 6 && digitalRead(SW) = LOW)
    {
      menuSix();
    }
  }
menuExit:
}
/**************меню - 1 - установка таймера в минутах**********/
void menuOne ()
{
  while (digitalRead(SW) == LOW)
  {
    encoder ();
    if (counter > 240)
      counter = 240;
    lcd.clear();
    minTimer = counter;
    lcd.print("Timer:");
    lcd.print(minTimer);
    lcd.print("min");
    delay(300);
  }
  counter = 0;
}
/**************меню - 2 - установка темпиратуры**********/
void menuTwo ()
{
  while (digitalRead(SW) == LOW)
  {
    encoder ();
    if ( counter > 220)
      counter = 220;
    lcd.clear();
    temp = counter;
    lcd.print("Temp");
    lcd.print(temp);
    lcd.print("C");
    delay(300);
  }
  counter = 0;
}
/**************меню - 3 - обнуление таймера и термпиратуры**********/
void menuThree ()
{
  while (digitalRead(SW) == LOW)
  {
    lcd.print("Press OK to resrt Timer and Temp.");
  }
  minTimer = 0;
  temp = 0;
}
/**************меню - 4 - установка времени**********/
void menuFour ()
{
  int yy = 0;
  byte mon = 0;
  byte dd = 0;
  byte hh = 0;
  byte mm = 0;
  // This line sets the RTC with an explicit date & time, for example to set
  // January 21, 2014 at 3am you would call:
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  counter = 2016;  //Присваивание 2016 для первого значения года
  while (digitalRead(SW) == LOW)  //Установка года
  {
    encoder ();
    lcd.clear();
    yy = counter;
    lcd.print("Year:");
    lcd.print(yy);
    delay(300);
  }
  counter = 1;
  while (digitalRead(SW) == LOW)  // Установка месяца
  {
    encoder ();
    if ( counter > 12)
      counter = 0;
    lcd.clear();
    mon = counter;
    lcd.print("Month");
    lcd.print(mon);
    delay(300);
  }
  counter = 1;
  while (digitalRead(SW) == LOW)   // Установка даты
  {
    encoder ();
    if ( counter > 31)
      counter = 0;
    lcd.clear();
    dd = counter;
    lcd.print("Date");
    lcd.print(dd);
    delay(300);
  }
  counter = 0;
  while (digitalRead(SW) == LOW)   //Установка часа
  {
    encoder ();
    if ( counter > 24)
      counter = 0;
    lcd.clear();
    hh = counter;
    lcd.print("Hour");
    lcd.print(hh);
    delay(300);
  }
  counter = 0;
  while (digitalRead(SW) == LOW)   // Установка минут
  {
    encoder ();
    if ( counter > 60)
      counter = 0;
    lcd.clear();
    mm = counter;
    lcd.print("Minutes");
    lcd.print(mm);
    delay(300);
  }
  counter = 0;
  rtc.adjust(DateTime(yy, mon, dd, hh, mm, 0)); // Отправка значения в РТЦ
}
/**************меню - 5 - выбор рабочих тенов**********/
void menuFive ()
{
  lcd.print(" V procrsse");
}
/**************меню - 6 - выход из меню **********/
void menuSix ()
{
  while (digitalRead(SW) == LOW)   // Установка минут
  {
    lcd.clear();
    lcd.print("To exit from menu press ok");
  }
  goto menuExit; ///////////////////С переходом не ясно. Откатать.
}

Вроде бы все хорошо, но не все ((( Выдает сей код 3 ошибки, от которых я решительно не могу избавиться, а по сему прошу Вашей помощи! Там наверное какая-то мелочь и по этому прошу сильно не пинать. Просто ткните пальцем, что не так. За ранее спасибо. 

Araris
Offline
Зарегистрирован: 09.11.2012

Приведите текст сообщений об ошибках.

И сразу поменяйте в ifах (187-207) && digitalRead(SW) = LOW) на  && digitalRead(SW) == LOW)

MaxiumTM
Offline
Зарегистрирован: 13.06.2016

Спасибо за подсказку!

А вот и ошибки:

 
C:\Users\Макс\Desktop\main4\main4.ino: In function 'void loop()':
 
main4:123: error: expected '}' before 'else'
 
C:\Users\Макс\Desktop\main4\main4.ino: At global scope:
 
main4:150: error: expected unqualified-id before 'else'
 
main4:154: error: expected declaration before '}' token
 
exit status 1
expected '}' before 'else'
 
DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

У вас while не закрыт, начиная со строки 076 - открывающая скобка есть, закрывающая - непонятно где. Кол-во открывающих и закрывающих скобок должно быть одинаково - ищите, где пропущена закрывающая скобка. Навскидку - я сказал, проверил, скопировав ваш код в Notepad++ - точно, показывает парную скобку для while в строке 076 перед else в строке 123 - непорядок.

Araris
Offline
Зарегистрирован: 09.11.2012

Ну а две последующие ошибки проистекают из первой.

Araris
Offline
Зарегистрирован: 09.11.2012

Управление нагревателем (строки 85-92) слишком уж "в лоб" прописано, почитайте http://radiostorage.net/?area=news/1961 , разберитесь, что я имею в виду.

Строки 141-148 - та же история с вентилятором.

MaxiumTM
Offline
Зарегистрирован: 13.06.2016

Разобрался с теми ошибками. Всему виной была скобки ))

Но возникли новые вопросы.

На данный момент самый глобальный - обработка прерываний от инкрементного энкодера.

На данный момент код имеет следующий вид:

////////////////////////////////////////////////////////
//Определение для часов реального времени ДС1307
#include <Arduino.h>
#include <Wire.h>         // this #include still required because the RTClib depends on it
#include "RTClib.h"

RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//////////////////////////////////////////////////////////
/* Define digital pins used to read the encoder */
#define DT 2
#define CLK 3
//int DT = 0;
//int CLK = 0;
#define SW 4
byte counter = 0;          //переменная для присвоения значений
/////////////////////////////////////////////////////////////
//Другое разное
int n = 0;             //Счетчик цикла
byte minTimer = 0;     // Таймер работы духовки
////////////////////////////////////////////////////////////
//Подключения дисплея
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
////////////////////////////////////////////////////////////
//Порт и переменная и прочее для поучения значения темпиратуры и вычислений
byte analogPin = 0;     // номер порта к которому подключен потенциометр
int tempInput = 0;      // переменная для хранения считываемого значения темпиратуры
byte temp = 0;          //переменная для хранения заданного значения темпиратуры
/////////////////////////////////////////////////////////////
int hotterPin = 15;     // Светодиод, подключенный к вход/выходу 13 - ТЭН
int coollerPin = 4;     // Вентилятор выдува горячего воздуха из корпуса.
//////////////////////////////////////////////////////////////
byte timerBuffer = 0;   //Промежуточная переменная для вычисления
byte midiPin = 6;       //Пин звукового сигнала
/////////////////////////////////

/////////////////////////////////
#define menuExit
//////////
void setup()
{
  lcd.begin(20, 4);     //объявление размеров дисплея (кол-во символов, кол-во строк)
  // Print a message to the LCD и установка курсора
  lcd.setCursor(1, 1);
  lcd.print("Hello :)");
  delay(2000);
  //Определение входов энкодера.
  pinMode(DT, INPUT);
  pinMode(CLK, INPUT);
  pinMode(SW, INPUT);
  digitalWrite(SW, HIGH);
  //Определение пина управления теном и вентилдятором, назначает режим работы - выход
  pinMode(hotterPin, OUTPUT);
  pinMode(coollerPin, OUTPUT);
  //Определение пина Миди
  pinMode(midiPin, OUTPUT);
  //кусок от РТЦ.
  if (! rtc.begin())
  {
    lcd.print("Couldn't find RTC");
    while (1);
  }
  if (! rtc.isrunning())
  {
    lcd.print("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }  //конец куска от РТЦ
//  attachInterrupt(0, encoderzero, RISING); //Разрешение прерывания 0
//  attachInterrupt(1, encoderone, RISING);  //Разрешение прерывания 1
//  Serial.begin(9600);
//  Serial.println("Basic Encoder Test:");
}
/* Main program */

void loop()
{
  if (digitalRead(SW) == LOW) //Чтение нажатия кнопки энкодера
  {
    goToMenu(); //Не идет
  }
  n++; //Прибавление еденички к счетчику входа в цикл
  while (n == 10000)  //вход в цикл измерения параметров, чтения и отображения времени. 1 раз в N оборото.
  {
    n = 0;
    tempInput = analogRead(analogPin);  //Чтение значения темпиратуры.  *******Нужно провести какие-то пересчеты промежуточные
    lcd.clear();
    lcd.setCursor(4, 0);
    if (minTimer > 0) //при выполнении условия духовка работает.
    {
      //Код работы духовки при значении таймера больше нуля.
      if (tempInput > temp)    //Проверка условия вкл/выкл ТЭНа.
      {
        digitalWrite(hotterPin, LOW);    // выключает тен духовки
      }
      else
      {
        digitalWrite(hotterPin, HIGH);    // включает тен духовки
      }
      DateTime now = rtc.now();    //Чтения текущего времени из РТЦ
      if (timerBuffer == (now.minute(), DEC))
      {
        // Нет никакого действия
      }
      else
      {
        minTimer = minTimer - 1;
        timerBuffer = (now.minute(), DEC);
        if (minTimer == 0)
          digitalWrite(hotterPin, LOW);  //Выключение ТЭНа
        for (int i = 0; i <= 30; i++)  //Время пищания 30 оборотов
        {
          digitalWrite(midiPin, HIGH);
          delay(400);
          digitalWrite(midiPin, LOW);
          delay(200);
          digitalWrite(midiPin, HIGH);
          delay(400);
          digitalWrite(midiPin, LOW);
          delay(1000);
        }
      }

      lcd.print("Time left:");
      lcd.print(minTimer);
      lcd.setCursor(2, 2);
      lcd.print("Temp:");
      lcd.print(tempInput);
    }//конец рабочего кода
    else //иначе идет индикация времени.
    {
      DateTime now = rtc.now();
      lcd.print(" (");
      lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
      lcd.print(") ");
      lcd.setCursor(6, 1);
      lcd.print(now.day(), DEC);
      lcd.print('/');
      lcd.print(now.month(), DEC);
      lcd.print("/");
      lcd.print(now.year(), DEC);
      lcd.setCursor(5, 3);
      lcd.print("Time:");
      lcd.print(now.hour(), DEC);
      lcd.print(':');
      lcd.print(now.minute(), DEC);
    }
    if (tempInput > 50)  //Проверка услови вкл/выкл вентилятора выдува из корпуса духовки
    {
      digitalWrite(coollerPin, HIGH);   // включает вентилятор на выдув из корпуса духовки
    }
    else
    {
      digitalWrite(coollerPin, LOW);    //выключает вентилятор на выдув из корпуса духовки
    }

  }	 //конец цикла измерения параметров или отображения времени.

}//Конец цикла всей программы
/*************************Обработка энкодера**************/

/**********************Menu*************************/
void goToMenu() //Переход есть. Расписать все красиво.
{
  lcd.clear();
  lcd.print("Rotate the knob to");
  lcd.setCursor(0, 1);
  lcd.print("select menu. Press");
  lcd.setCursor(0, 2);
  lcd.print("the knob to select.");
  delay(3000);
  byte var = 0;
  while (1)
  {
    
    delay(200);
    lcd.clear();
    encoder();
    if ( counter >= 6)
    {
      counter = 1;
    }
    if (counter <= 1)
    {
      counter = 6;
    }
    var = counter;
    if (var == 1)
    {
      lcd.print("Set timer");
      if (digitalRead(SW) == LOW)
      {
        menuOne();
      }
    }
    else if (var == 2)
    {
      lcd.print("Set temp");
      if (digitalRead(SW) == LOW)
      {
        menuTwo();
      }
    }
    else if (var == 3)
    {
      lcd.print("Reset timer & temp");
      if (digitalRead(SW) == LOW)
      {
        menuThree();
      }
    }
    else if (var == 4)
    {
      lcd.print("Set Time");
      if (digitalRead(SW) == LOW)
      {
        menuFour();
      }
    }
    else if (var == 5)
    {
      lcd.print(" V processe");
      if (digitalRead(SW) == LOW)
      {
        menuFive();
      }
    }
    else if (var == 6)
    {
      lcd.print("Exit from Menu");
      if (digitalRead(SW) == LOW)
      {
        menuSix();
      }
    }
  }
  menuExit;
}
/**************меню - 1 - установка таймера в минутах**********/
void menuOne ()
{
  while (digitalRead(SW) == LOW)
  {
    // encoder ();
    if (counter > 240)
      counter = 240;
    lcd.clear();
    minTimer = counter;
    lcd.print("Timer:");
    lcd.print(minTimer);
    lcd.print("min");
    delay(300);
  }
  counter = 0;
}
/**************меню - 2 - установка темпиратуры**********/
void menuTwo ()
{
  while (digitalRead(SW) == LOW)
  {
    // encoder ();
    if ( counter > 220)
      counter = 220;
    lcd.clear();
    temp = counter;
    lcd.print("Temp");
    lcd.print(temp);
    lcd.print("C");
    delay(300);
  }
  counter = 0;
}
/**************меню - 3 - обнуление таймера и термпиратуры**********/
void menuThree ()
{
  while (digitalRead(SW) == LOW)
  {
    lcd.print("Press OK to resrt Timer and Temp.");
  }
  minTimer = 0;
  temp = 0;
}
/**************меню - 4 - установка времени**********/
void menuFour ()
{
  int yy = 0;
  byte mon = 0;
  byte dd = 0;
  byte hh = 0;
  byte mm = 0;
  // This line sets the RTC with an explicit date & time, for example to set
  // January 21, 2014 at 3am you would call:
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  counter = 2016;  //Присваивание 2016 для первого значения года
  while (digitalRead(SW) == LOW)  //Установка года
  {
    // encoder ();
    lcd.clear();
    yy = counter;
    lcd.print("Year:");
    lcd.print(yy);
    delay(300);
  }
  counter = 1;
  while (digitalRead(SW) == LOW)  // Установка месяца
  {
    // encoder ();
    if ( counter > 12)
      counter = 0;
    lcd.clear();
    mon = counter;
    lcd.print("Month");
    lcd.print(mon);
    delay(300);
  }
  counter = 1;
  while (digitalRead(SW) == LOW)   // Установка даты
  {
    // encoder ();
    if ( counter > 31)
      counter = 0;
    lcd.clear();
    dd = counter;
    lcd.print("Date");
    lcd.print(dd);
    delay(300);
  }
  counter = 0;
  while (digitalRead(SW) == LOW)   //Установка часа
  {
    // encoder ();
    if ( counter > 24)
      counter = 0;
    lcd.clear();
    hh = counter;
    lcd.print("Hour");
    lcd.print(hh);
    delay(300);
  }
  counter = 0;
  while (digitalRead(SW) == LOW)   // Установка минут
  {
    //encoder ();
    if ( counter > 60)
      counter = 0;
    lcd.clear();
    mm = counter;
    lcd.print("Minutes");
    lcd.print(mm);
    delay(300);
  }
  counter = 0;
  rtc.adjust(DateTime(yy, mon, dd, hh, mm, 0)); // Отправка значения в РТЦ
}
/**************меню - 5 - выбор рабочих тенов**********/
void menuFive ()
{
  lcd.print(" V procrsse");
}
/**************меню - 6 - выход из меню **********/
void menuSix ()
{
  while (digitalRead(SW) == LOW)   // Установка минут
  {
    lcd.clear();
    lcd.print("To exit from menu press ok");
  }
  goto menuExit;///////////////////С переходом не ясно. Откатать.
}

 

В 73 и 74 строках разрешаем прерывания 0 и 1. У каждого прерывания своя функция. А что дальше делать - ума не приложу. Перепробовал массу вариантов и не удается получить приемлемый вариант. Получаются большие скачки значений при вращении энкодера на 1 щелчек и при вращении в одну сторону приходят значения как в сторону увеличения, так и уменьшения.

П.С. Код обработки прерываний вытер, нет сил моих показывать его людям.

MaxiumTM
Offline
Зарегистрирован: 13.06.2016

Нашел на форуме решение проблемы (:

Если вдруг кому нужно - http://arduino.ru/forum/programmirovanie/lcd-enkoder#comment-86489