Помогите с кодом :)
- Войдите на сайт для отправки комментариев
Пнд, 13/06/2016 - 16:23
База - Ардуино Нано в 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 ошибки, от которых я решительно не могу избавиться, а по сему прошу Вашей помощи! Там наверное какая-то мелочь и по этому прошу сильно не пинать. Просто ткните пальцем, что не так. За ранее спасибо.
Приведите текст сообщений об ошибках.
И сразу поменяйте в ifах (187-207) && digitalRead(SW) = LOW) на && digitalRead(SW) == LOW)
Спасибо за подсказку!
А вот и ошибки:
У вас while не закрыт, начиная со строки 076 - открывающая скобка есть, закрывающая - непонятно где. Кол-во открывающих и закрывающих скобок должно быть одинаково - ищите, где пропущена закрывающая скобка. Навскидку - я сказал, проверил, скопировав ваш код в Notepad++ - точно, показывает парную скобку для while в строке 076 перед else в строке 123 - непорядок.
Ну а две последующие ошибки проистекают из первой.
Управление нагревателем (строки 85-92) слишком уж "в лоб" прописано, почитайте http://radiostorage.net/?area=news/1961 , разберитесь, что я имею в виду.
Строки 141-148 - та же история с вентилятором.
Разобрался с теми ошибками. Всему виной была скобки ))
Но возникли новые вопросы.
На данный момент самый глобальный - обработка прерываний от инкрементного энкодера.
На данный момент код имеет следующий вид:
//////////////////////////////////////////////////////// //Определение для часов реального времени ДС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 щелчек и при вращении в одну сторону приходят значения как в сторону увеличения, так и уменьшения.
П.С. Код обработки прерываний вытер, нет сил моих показывать его людям.
Нашел на форуме решение проблемы (:
Если вдруг кому нужно - http://arduino.ru/forum/programmirovanie/lcd-enkoder#comment-86489