Создание "меню" на arduino

arturmon
Offline
Зарегистрирован: 02.07.2011

Добрый день.

собрал "градусник" "часы" и " регулятор нагрушки через ШИМ" но требуется изменять некоторые значения мин и макс температуры срабатывания "регулятора нагрузки". но в интернете нет примеров создания "меню" для arduino. может кто имеет опыт создания меню для arduino? как оно делается? :-)

и еще один вопрос часы странно работаю. собраны на ds1307 как включаешь только тогда часы и начинают идти. хотя если установить дату он запоминает! убираешь батарейку он скидывает дату до 1970. значит часы работают, но почему то не идут когда нет питания.

 

 

Adessit
Adessit аватар
Offline
Зарегистрирован: 12.04.2011

Для ds1307 по любому должна быть батарейкана на 3В. 

Adessit
Adessit аватар
Offline
Зарегистрирован: 12.04.2011

Примеры с меню есть, если найду выложу ссылку. А на чем идёт вывод информации? 

arturmon
Offline
Зарегистрирован: 02.07.2011

вывод идет LCD 16x2, батарейку уже новую поставил cr2025 3v все равно такая байда :-(

меню откопал но что то разобраться не могу, он написан на с. но что то не вкурил.

/////////////////////////menu//////////////////////////////////////
char kod;
char last_item;
int current_menu=0; //Переменная указывает на текущее меню
int current_poz=1; //Переменная указывает на текущий пункт меню/подменю
void goto_menu(void);
void print_menu(void);

typedef struct _selection
{
unsigned char *mas; // Указатель на название пункта
void (*function)(void); //Указатель на функцию выполняющуюся по нажатии на enter/escape
unsigned ent_f: 4; //Флаг входа 4 бита - обычно ID меню в которое надо войти
unsigned esc_f: 4; //Флаг выхода 4 бита - обычно ID меню в которое надо вернуться
}SELECTION;

//Структура описывает меню/подменю
typedef struct _menu {
unsigned char id; //Номер меню/подменю
unsigned char num_selections; //Количество пунктов данного меню/подменю
SELECTION *m; //Указатель намассив пунктов данного меню/подменю
}MENU;

//Номера меню/подменю
enum __menu__id {
MAIN_MENU, //Главное меню
DELAY_MENU, //Меню настроек
FOCUS_MENU,
QUANTITY_MENU, 
TIME_MENU //Меню отчёта
};

//Имена пунктов
unsigned char X1[]={"Задержка"}; 
unsigned char X2[]={"1 сек"};
unsigned char X3[]={"2 сек"};
unsigned char X4[]={"3 сек"};
unsigned char X5[]={"4 сек"};
unsigned char X6[]={"5 сек"};
unsigned char X7[]={"8 сек"};
unsigned char X8[]={"10 сек"};
unsigned char X9[]={"15 сек"};
unsigned char X10[]={"20 сек"};
unsigned char X11[]={"30 сек"};
unsigned char X12[]={"Фокусировка"};
unsigned char X13[]={"Выкл"};
unsigned char X14[]={"0,5 сек"};
unsigned char X15[]={"1 сек"};
unsigned char X16[]={"Кол. фоток"};
unsigned char X17[]={"50 шт"};
unsigned char X18[]={"100 шт"};
unsigned char X19[]={"200 шт"};
unsigned char X20[]={"300 шт"};
unsigned char X21[]={"500 шт"};
unsigned char X22[]={"800 шт"};
unsigned char X23[]={"1000 шт"};
unsigned char X24[]={"Время фотогр."};
unsigned char X25[]={"Непрерывно"};
unsigned char X26[]={"5 мин"};
unsigned char X27[]={"10 мин"};
unsigned char X28[]={"15 мин"};
unsigned char X29[]={"пол часа"};
unsigned char X30[]={"час"};
unsigned char X31[]={"два часа"};
unsigned char X32[]={"Старт съемки"};

//Заголовки функций
void func1(void);
void func2(void)
{
// do {
// analogButtons.checkButtons();
// lcd.clear(); //очистить LCD
// lcd.print("Hello World!"); //вывод строки на LCD
// delay(1000); //задержка для проверки
// } while ( != 5); //Для выхода - ESC
}
void func3(void);
void func4(void);
void func5(void);
void func6();
void func7(void);

//Массив хранищий пункты главного меню (структура SELECTION)
static SELECTION menu_[]={
{X1, goto_menu, DELAY_MENU, MAIN_MENU}, //Punkt 1
{X12, goto_menu, FOCUS_MENU, MAIN_MENU}, //Punkt 2
{X16, goto_menu, QUANTITY_MENU, MAIN_MENU}, //Punkt 3
{X24, goto_menu, TIME_MENU, MAIN_MENU}, //Punkt 4
{X32, func7, 0, 0} //Punkt 4 
};

//Массив хранищий пункты меню настроек (структура SELECTION)
static SELECTION menu_m0[]={
{X2, func6, 0, 0}, //Punkt 1
{X3, func6, 0, 0}, //Punkt 2
{X4, func6, 0, 0}, //Punkt 3 
{X5, func6, 0, 0}, //Punkt 2
{X6, func6, 0, 0}, //Punkt 2
{X7, func6, 0, 0}, //Punkt 2 
{X8, func6, 0, 0}, //Punkt 2 
{X9, func6, 0, 0}, //Punkt 2 
{X10, func6, 0, 0}, //Punkt 2 
{X11, func6, 0, 0} //Punkt 2 
};
static SELECTION menu_m1[]={
{X13, func6, 0, 0}, //Punkt 1
{X14, func6, 0, 0}, //Punkt 2
{X15, func6, 0, 0} //Punkt 3 
}; 
static SELECTION menu_m2[]={
{X17, func6, 0, 0}, //Punkt 1
{X18, func6, 0, 0}, //Punkt 2
{X19, func6, 0, 0}, //Punkt 3 
{X20, func6, 0, 0}, //Punkt 1
{X21, func6, 0, 0}, //Punkt 2
{X22, func6, 0, 0}, //Punkt 3 
{X23, func6, 0, 0} //Punkt 1
};
static SELECTION menu_m3[]={
{X25, func6, 0, 0}, //Punkt 1
{X26, func6, 0, 0}, //Punkt 2
{X27, func6, 0, 0}, //Punkt 3 
{X28, func6, 0, 0}, //Punkt 1
{X29, func6, 0, 0}, //Punkt 2
{X30, func6, 0, 0}, //Punkt 3 
{X31, func6, 0, 0} //Punkt 1
};
//Главный массив хранит в себе все меню/подменю
//Все меню/подменю должны описываться в таком же порядке как и в enum __menu__id ...
static MENU menu[] = {
{MAIN_MENU, 5, menu_}, //Меню 1
{DELAY_MENU, 10, menu_m0}, //Меню 2 
{FOCUS_MENU, 3, menu_m1},
{QUANTITY_MENU, 7, menu_m2},
{TIME_MENU, 7, menu_m3}
};
///////////////////////END_menu////////////////////////////////////////
 

 void goto_menu(void) 
{
switch (kod) {
case 'e': 
{current_menu=menu[current_menu].m[current_poz].ent_f; last_item=current_poz; break;}; //enter
break;
case 'b': 
{current_menu=menu[current_menu].m[current_poz].esc_f; break;}; //escape }
break;
default:
current_poz=0;
}
}

void print_menu()
{
lcd.clear();
lcd.print("> ");
//lcd.print(menu[current_menu].m[current_poz].mas);


//тут непонятки "м" was not declare in this score
//хотя массив вроде заведен


lcd.print(current_menu);
lcd.setCursor(2,1);
if (current_poz == menu[current_menu].num_selections-1) 
{
// lcd.print(menu[current_menu].m[0].mas);
lcd.print("----------------");
}
else 
{
// lcd_puts(menu[current_menu].m[current_poz+1].mas);
kod=m[current_poz+1].mas;
; lcd.setCursor(m[current_poz+1].mas);
lcd.print(kod);
}
delay_ms(100); 
kod='k';
}

 

arturmon
Offline
Зарегистрирован: 02.07.2011

http://electronix.ru/forum/index.php?showtopic=14289&st=30

оригинал находится тут. 

Adessit
Adessit аватар
Offline
Зарегистрирован: 12.04.2011

по поводу батарейки, может у вас схема собрано криво. Давайте фото схемы и как вы это собрали 

arturmon
Offline
Зарегистрирован: 02.07.2011

1,2 нога кварц

3 +3 батарейки

4 масса

5 sda

6 scl

7 ----

8 +5v

вот так подключенно 

arturmon
Offline
Зарегистрирован: 02.07.2011

на 4 ноге еще минус батарейки висит 

pistoletov
Offline
Зарегистрирован: 15.08.2011

 Подобная проблема была когда нагрузка индуктивная включалась. Часы останавливались. Проблемарешилась конденсатором на ножки питаня ds1307. Меню сделал с помощью ротари энкодера

 

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 А можно поподробнее, про меню с помощью ротари энкодера ?

ourlive
Offline
Зарегистрирован: 26.05.2012

sla/sda к чему притянуты? библиотека на эти часики не одна, и на них есть команда start/stop работы таймера. вот и смотрите кто и как отдаёт команду стоп.

а на счёт энкодета.. спорно довольно. для вашего меню достаточно 3х кнопок. либо энкодер и кнопка, но логика работы с энкодером требует или отдельной библы или самому писать, что не в пользу минимизации скетча.

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 Ребята, а где можно почитать про работу с меню, энкодером с кнопкой ?

pistoletov
Offline
Зарегистрирован: 15.08.2011

 Я брал энкодер с функцией нажатия.  Пользовался готовой библиотекой для ардуины - нашел просто в инете. Меню делал простенькое одного уровня без вложений. Вроде все симпотно получилось - энкодером выставляю время полива для автомата или включаю ручной полив. Скетч есть но он без коментариев - кому нужно - поделюсь

 

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 Было бы не плохо. А схему не покажите, чтобы легче было понимать скетч ?

ourlive
Offline
Зарегистрирован: 26.05.2012

на счёт менюхи, неплохо бы соорудить библиотеку соответствующую (или может кто то знает где взять?) хотя бы для простого древовидного меню. Недавно пытался в скетче городить такую штуку, не очень то оно просто. И при этом переехать на другой тип экрана не реально (например с LCD на одно-двухстрочный цифробуквенный), по крайней мере на моём варианте...

pistoletov
Offline
Зарегистрирован: 15.08.2011

 пока ищу файлики - подскажите как выложить их сюда

 

leshak
Offline
Зарегистрирован: 29.09.2011

ourlive пишет:

на счёт менюхи, неплохо бы соорудить библиотеку соответствующую (или может кто то знает где взять?) 

Ну в гугле или arduino.cc поискать :).

В.И.Савченко пишет:
Прежде чем делать открытие — загляни в справочник.
К. Прутков-инженер. «Советы начинающему гению»  

Например вот http://arduino.cc/playground/Code/Menu

Вот пример использование с LCD, а не Serial http://www.coagula.org/content/pages/tutorial-manage-menu-and-lcd-displa...

Вот другая библиотека

https://github.com/jonblack/menusystem

Лично мне она более симпатична. Не нужно делать общую портянку switch, можно привесить "функцию-обработчик" к каждому пункту

http://jonblack.org/2012/05/14/arduino-library-for-creating-a-menu-system/

 

 

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 leshak, спасибо большое за линки но, там с кнопками, а мне бы энкодер с кнопкой... Знаете что- нибудь такое ?

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 pistoletov, здесь Форумы- Программирование- Вставка программного кода в тему/комментарий показано, как вставлять код в сообщение

leshak
Offline
Зарегистрирован: 29.09.2011

mat пишет:

 leshak, спасибо большое за линки но, там с кнопками, а мне бы энкодер с кнопкой... Знаете что- нибудь такое ?

Я вообще не вам отвечал. Вы - в моем личном игноре.  Так что задавать вопросы персонально мне - можете не трудится.

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 Хорошо, не буду. Всё равно отвечаете не по делу.

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 pistoletov, ну что там, нашлись файлы ? Ждать ? Или не стОит ?

pistoletov
Offline
Зарегистрирован: 15.08.2011

 Скетч нашел. Выложу сегодня вечером. Схему класть не буду  - так как все понятно из скетча - 3 провода на энкодер и 6 проводов на экранчик. Остальные 3 провода - управление исполнительными устройствами полива(клапана и насос). 

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 Спасибо большое. Ждём.

Borland
Offline
Зарегистрирован: 17.05.2012

для Serial интерфейса,при реализации своего таймера написал простенькое вертикальное меню, до горизонтального не дошло ,хотя планировал

нужны 2 инклуда - Один распространенный везде Ansiterm.h, но я чегото в нем модифицировал, поэтому прикладываю ( помойму поменял местами row и column.

второй Slot.h - там две структуры, одна для ввода и редактирования каких либо данных, вторая собственно меню , ну и какието утилиты типа обработки кнопок типа стрелок содержащих ESC посследовательности

Кому редактирование не нужно , можно выкинуть все что связано со структурой Slot

перетащил щас это на Arduino 1.0 работате но с кучей варнингов.

меню с разными бордюрами(псевдографика, которая даже вроде лежит в PROGMEM но проверять не умею) , количеством Items , размер меню можно задать равным от 1  до 23 полагаю( кол-во строк на экране)

единственно следить за расположением, сам код тупо прибавляет к координатам экрана элементы меню.

 

по двум ESQ выход из меню с return 0, по одному не получилост так как обрабатываются ESC последовательности типа стрелок на IBM клавиатуре.

в Гипертерминале необходимо включить режим эмуляции ANSI ну и скорость поставить 115 кбод ( не так заметно прорисовки экрана)

полагаю что легко переделывается на lcd заменой Screen-xy на lcd позиционирование и Serial.write на lcd.вывод

Btw работает на PS клавиатуре подключенной к ардуине, но требует замены метода Serial.read, выкинул за ненадобностью.

код примера


#if ARDUINO < 100
#include "WProgram.h"
#else
#include "Arduino.h"
#endif
#include <Slot.h>
#include <AnsiTerm.h>

Ansiterm SCRN;    
char *MenuTable[]={
      "Set Time",
      "Program A",
      "Program B",
      "Program C",
      "Program S",
      "Sensitivity",
      "Loop ",
      "Show Temperature",
      "Show Relay State",
      "Show Hummidity",
      "Set Temp Limits",
      "Turn On Radio",
      "War with China"
      };

extern unsigned char AnyKey(void);
void setup () {

  Serial.begin(9600);

}
void loop() {
SCRN.eraseScreen(); 
Menu mStartTime;
mStartTime.Title="test menu";
mStartTime.style=11;
mStartTime.length=20;
mStartTime.depth=1;
mStartTime.ItemsList=MenuTable;
mStartTime.CurrentItem=0;
mStartTime.NumberOfItems=13;
mStartTime.FirstItem=0;

   switch (mStartTime.Run(5,3)) {
     case 1:
          
         // enter  code here
         Serial.println("1\n");
         AnyKey();
            
         break;
     case 4:
          
         // enter  code here
         Serial.println("4\n");
         AnyKey();
            
         break;
     case 2:
          
         // enter  code here
         Serial.println("2\n");
         AnyKey();
            
         break;
     case 3:
          
         // enter  code here
         Serial.println("3\n");
         AnyKey();
            
         break;
 
   } // end switch 
}

как вложить файлы, ума не приложу, попробую следующим постом

Borland
Offline
Зарегистрирован: 17.05.2012

Распространненный в сети Ansiterm слегка подправленый, инклуд родной от разработчика

собственно используется от него только позиционирование и инверсия выбранного itema

 

/* 
Ansiterm.cpp -- an Arduino library that simplifies using the ANSI terminal
control escape sequences. This allows your code to  position text exactly in the
terminal, to add colour and other effects. To use Ansiterm, an ANSI terminal must
be connected to the Arduino's serial port. The terminal built into the Arduino 
IDE does not respond to the ANSI codes, but most MacOs and Linux terminals do. 
In Windows, I read that Hyperterm responds to ANSI codes. Realterm responds to most
codes, but will not change the color of the foreground.

The accompanying example file illustrates the library's use.

Copyright (c) 2009 Bruce Robertson, VE9QRP. All rights reserved.

This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option)
any later version.

This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.

You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

The latest version of this software is available at
*/

#if ARDUINO < 100
#include "WProgram.h"
#else
#include "Arduino.h"
#endif

#include "Ansiterm.h"
#ifdef BORLAND
#include "HS.h"
extern Ser Serial;
#endif

Ansiterm::Ansiterm()
{
}


void Ansiterm::home()
{
  preamble();
  Serial.write('H');
}


void Ansiterm::xy(int y, int x)
{
  preamble();
  Serial.print(y,DEC);
  Serial.write(';');
  Serial.print(x, DEC);
  Serial.write('H');
}


void Ansiterm::up(int x)
{
  preambleAndNumberAndValue(x,'A');
}


void Ansiterm::down(int x)
{
  preambleAndNumberAndValue(x,'B');
}


void Ansiterm::forward(int x)
{
  preambleAndNumberAndValue(x,'C');
}


void Ansiterm::backward(int x)
{
  preambleAndNumberAndValue(x,'D');
}


void Ansiterm::eraseLine()
{
  preamble();
  Serial.write('2');
  Serial.write('K');
}


void Ansiterm::eraseScreen()
{
  preamble();
  Serial.write('2');
  Serial.write('J');
}


void Ansiterm::setBackgroundColor(int color)
{
  setAttribute(color + 40);
}


void Ansiterm::setForegroundColor(int color)
{
  setAttribute(color + 30);
}


void Ansiterm::boldOn()
{
  setAttribute(BOLD_ON);
}


void Ansiterm::boldOff()
{
  setAttribute(BOLD_OFF);
}


void Ansiterm::italicsOn()
{
  setAttribute(ITALICS_ON);
}


void Ansiterm::italicsOff()
{
  setAttribute(ITALICS_OFF);
}


void Ansiterm::underlineOn()
{
  setAttribute(UNDERLINE_ON);
}


void Ansiterm::underlineOff()
{
  setAttribute(UNDERLINE_OFF);
}


void Ansiterm::strikethroughOn()
{
  setAttribute(STRIKETHROUGH_ON);
}


void Ansiterm::strikethroughOff()
{
  setAttribute(STRIKETHROUGH_OFF);
}


void Ansiterm::inverseOn()
{
  setAttribute(INVERSE_ON);
}


void Ansiterm::inverseOff()
{
  setAttribute(INVERSE_OFF);
}


void Ansiterm::reset()
{
  setAttribute(RESET);
}


void Ansiterm::defaultBackground()
{
  setAttribute(DEFAULT_BACKGROUND);
}


void Ansiterm::defaultForeground()
{
  setAttribute(DEFAULT_FOREGROUND);
}


void Ansiterm::fill(int y1, int x1, int y2, int x2)
{
  for (int x = x1; x <= x2; x++)
  {
    for (int y = y1; y <= y2; y++)
    {
      xy(x,y);
      Serial.print(' ',0);
    }
  }
}


/* private functions */
void Ansiterm::preamble()
{
  Serial.write(ESCAPE);
  Serial.write(BRACE);
}


void Ansiterm::preambleAndNumberAndValue(int x, char v)
{
  preamble();
  Serial.print(x,DEC);
  Serial.write(v);
}


void Ansiterm::setAttribute(int a)
{
  preambleAndNumberAndValue(a, 'm');
}

 

Borland
Offline
Зарегистрирован: 17.05.2012

ну и собственно Slot.h Slot.cpp в котором есть класс menu все что касается Slot можно выкинуть, но мне это нужно.

 

#if ARDUINO < 100
#include "WProgram.h"
#else
#include "Arduino.h"
#endif 
    
#ifdef __BORLANDC__
 #include "HS.h"
 #define PROGMEM
 #define pgm_read_byte(bu) *bu
// #define BUILD_FIELD(field) my_struct.inner_struct.union_a.##field
//  #token
#else
#include  <avr/pgmspace.h>
#include  <Ansiterm.h>
#endif


#include "Slot.h"





#ifndef __BORLANDC__
//#include "Memoryfree.h"
//#include "WProgram.h"
//#include <PS2Keyboard.h>
//extern PS2Keyboard keyboard;
#endif
#ifdef __BORLANDC__
extern Ser Serial;
#endif

PROGMEM unsigned char border[] ={0xDA,0xC4,0xBF,0xB3,0xC0,0xD9,
			0xC9,0xCD,0xBB,0xBA,0xC8,0xBC,
	            	0xD5,0xCD,0xB8,0xB3,0xD4,0xBE,
                        '+','=','+','|','+','+'
			 };

/*
}; */

//extern unsigned char AnyKey(void);






unsigned char AnyKey(void) {

while (!Serial.available());
/*#ifndef __BORLANDC__
 {

  if (keyboard.available())
      return keyboard.read();
 }
#endif */
 return Serial.read();

}
uint8_t LagerstString(char *items,uint8_t Items) {
uint8_t i;
uint8_t largest;
	for(i=0,largest=0;i<Items;i++)
	       if (strlen(items+i)>largest) largest=strlen(items+i);
	return largest;

}

unsigned char TranslateKey(char c) {
static unsigned char firsttime=0;
static unsigned char Esc_flag=0,VirtualKey;
static unsigned char Arrow_flag;
   VirtualKey=0;
a:
  if (!firsttime)
      firsttime++;
  else
      c=AnyKey();


  if (c>=192)
     if (c <= 239)
       c-=64;
     else
       c-=16;


 if (c==27) {
   if (Esc_flag==1) {
       VirtualKey=ESC;
       Esc_flag=0;

    } else {
       Esc_flag=1;
       goto a;
    }
  // maybe special key
 }


 if (Esc_flag==1 && c==91) {
     Arrow_flag=1;
    goto a;
   }
 if (Esc_flag==1 && c==27) {
     VirtualKey=ESC;
    }


 if (Esc_flag==1 && Arrow_flag==1) {
    switch (c) {
       case 68:
          VirtualKey=LEFT;
          break;
       case 65:
          VirtualKey=UP;
          break;
       case 66:
          VirtualKey=DOWN;
          break;
       case 67:
          VirtualKey=RIGHT;
          break;

    }
    Esc_flag=Arrow_flag=0;

  } //endif
 if (VirtualKey==0 && Esc_flag==0 && Arrow_flag==0)
        VirtualKey=c;
 firsttime=0;
 return VirtualKey;



}


void Menu::DrawItems() {
  uint8_t  i;
  char *z;
  for (i=0;i<depth;i++) {
    Screen->xy(row+i,column);
    if (CurrentItem==FirstItem+i)
         Screen->inverseOn();
    Serial.write((uint8_t *)justify(0,length,ItemsList[FirstItem+i],' '),length);
    if (CurrentItem==FirstItem+i)
         Screen->inverseOff();
  }

}

 
uint8_t Menu::Run(uint8_t x, uint8_t y) {
uint8_t i,j;          
uint8_t offset=0;
uint8_t bord;
unsigned char c;
char *z;
  bord=style>>1&0x03;
  if(style&8) offset=1;
  if (style&1==1) { //Vertical
    if(!length) length=LagerstString(*ItemsList,NumberOfItems);
    if(!depth) depth=NumberOfItems;
    if (x!=0) {  // first time draw
          row=x;
          column=y;
    }
    if (offset) {
       Screen->xy(row-offset,column-offset);
       if (strlen(Title)>length) Title[length-2]='\0';
       Serial.write(pgm_read_byte(&border[bord*6]));
       z=justify(1,length+offset,Title,pgm_read_byte(&border[1+bord*6]));
       Serial.write((uint8_t*)z,length);
       Serial.write(pgm_read_byte(&border[2+bord*6]));
       for(i=0;i<depth;i++) {
         Screen->xy(row+i,column-offset);
         Serial.write(pgm_read_byte(&border[3+bord*6]));
         Screen->xy(row+i,column+length);
         Serial.write(pgm_read_byte(&border[3+bord*6]));
       }
       Screen->xy(row+i,column-offset);
//       Screen->xy(row+i+offset,column-offset);
       Serial.write(pgm_read_byte(&border[4+bord*6]));
       Serial.write((uint8_t*)justify(1,length,"",pgm_read_byte(&border[1+bord*6])),length);
       Serial.write(pgm_read_byte(&border[5+bord*6]));
       Screen->xy(row,column);
    }
       DrawItems();

       c=0;
       while (c!=ESC) {
           c=AnyKey();
           c=TranslateKey(c);
       switch (c) {
           case UP:
                  if (CurrentItem)
                       CurrentItem--;
                  if (FirstItem>CurrentItem)
                        FirstItem--;

                  break ;
           case DOWN:
                  CurrentItem++;
                  if (CurrentItem==NumberOfItems)
                       CurrentItem=NumberOfItems-1;
                  if(FirstItem+depth-1<CurrentItem)
                           FirstItem++;
                  break;
           case CR:
                  return CurrentItem+1;
                  break;


           default:
                break;
       }
        if (c!=ESC) c=0;
        DrawItems();
      }   //Endof while
      return 0;
  }  // Endof Vertical Menu;


}


extern Ansiterm SCRN;
void Slot::Draw(uint8_t x, uint8_t y, Slot *a)
{
unsigned char bord,i,j=0,k,wide,gap;
unsigned char  l;
char *z;
char c;
Slot empty;



Slot *pempty=a;
/*      SCRN.eraseScreen();
      Serial.print("****");
      Serial.print(this->style,DEC);
      Serial.print("****");
      if (this->style==(char)9) {  //  its a progMEM
        Serial.print("****");  */

/*
        z=(char*)a;
        for(i=0;i<sizeof(empty);i++) {
          *(((char *)&empty)+i)=
   	   pgm_read_byte(z+i);

        }  */ // read from PROGMEM ty empty bss;

/*        Serial.print("!");
        Serial.print(pempty->row,DEC);
        Serial.print("!");
        Serial.print("!");

        Serial.print(pgm_read_byte(a->row),DEC);
        Serial.print("!");
        Serial.print((unsigned int)&(a->row),HEX);
        Serial.print("*");
        Serial.print((unsigned int)&(pempty->row),HEX);


	AnyKey();          */
   	bord=pempty->style>>1&0x03;
  //      empty->length=LargestString(pempty->Title,pempty->Text,length);
          if (x!=0) {  // first time draw

               pempty->row=x;

               //column&=0x1F;
               //column|=y;
               pempty->column=y;
               //bord=row>>5;
               pempty->CursorPosition=0;
               if(!pempty->length) pempty->length=strlen(pempty->Text);
          }
  //     Serial.print(pempty->row,DEC);
  //     Serial.println();
  //     Serial.print(column,DEC);
  //     Serial.println();
      Screen->setForegroundColor(pempty->color);
   if ((pempty->style&1)==1) {  // Is a single Slot
      Screen->xy(pempty->row-1,pempty->column-1);
      if (pempty->length) wide=pempty->length;
      else wide=strlen(pempty->Text);
      if (strlen(pempty->Title)>wide) pempty->Title[wide-2]='\0';
//      pempty->length=wide;
      Serial.write(pgm_read_byte(&border[bord*6]));

      z=justify(1,wide,pempty->Title,pgm_read_byte(&border[1+bord*6]));
      Serial.write((uint8_t*)z,wide);


      Serial.write(pgm_read_byte(&border[2+bord*6]));

      Screen->xy(pempty->row,pempty->column-1);

      Serial.write(pgm_read_byte(&border[3+bord*6]));
//      Screen->inverseOn();
//     if (!specialedit)
          Serial.write(pempty->Text);
/*                else
          Serial.write(((*SpecialEdit)(0,pempty))); */

      k=pempty->length-strlen(pempty->Text);
      for (i=0;i<k;i++) {
         Serial.write((const uint8_t *)" ",1);
      }

//      Screen->xy(row,column+length+1);
//      Screen->inverseOff();
      Serial.write(pgm_read_byte(&border[3+bord*6]));
      Screen->xy(pempty->row+1,pempty->column-1);
      Serial.write(pgm_read_byte(&border[4+bord*6]));
      Serial.write((uint8_t*)justify(1,wide,"",pgm_read_byte(&border[1+bord*6])),wide);
      Serial.write(pgm_read_byte(&border[5+bord*6]));
      Screen->xy(pempty->row,pempty->column+CursorPosition);
//      SetForegroundcolor(pempty->color);

 }
   else  {
   //	Serial.println("i s not a Single");
    //	Serial.print("Column:");
      Screen->xy(pempty->row,pempty->column);
      z=justify(1,wide,pempty->Title,' ');
      Serial.write(z);
  //    Serial.println();
  }
}

char * justify(unsigned char center,unsigned char l,char *s,unsigned char b){
int i,j;

uint8_t len=strlen(s);
//Serial.write(s,(unsigned)len);
if (center) {
    int pos=(int)((l-len)/2);

    for (i=0; i<pos; i++)
    r[i]=b;
} else i=0;
strcpy(r+i,s);
for (j=len+i; j<l; j++)
    r[j]=b;
r[j]='\0';

return r;
}

int  Slot::Edit(Slot *a)
{
 int Esc_flag=0;
 int Arrow_flag=0;
 unsigned char c;
 unsigned char VirtualKey=0;
 unsigned char temp[80];
 Screen->xy(row,column);
a:
//Serial.println("6269");
 Draw(0,0,a);
 VirtualKey=0;
 c=AnyKey();
 VirtualKey=TranslateKey(c);
  if(specialedit) {
     (*SpecialEdit)(VirtualKey,this);
 //     Draw(0,0,a);
 //     goto a;
     }


// Serial.print(VirtualKey,DEC);
if (VirtualKey==RIGHT) {
    if (strlen(Text)>CursorPosition)
      CursorPosition++;
    Draw(0,0,a);

} else
if (VirtualKey==LEFT) {
    if (CursorPosition)
      CursorPosition--;
    Draw(0,0,a);

} else
if (VirtualKey==CTRLX) {
   CursorPosition=0;
   Text[0]='\0';
   Draw(0,0,a);
   goto a;
}

if (VirtualKey==DELETE) {
   CursorPosition++;
   VirtualKey=BACKSPACE;
}


if (VirtualKey==BACKSPACE) {
    if (CursorPosition) {
      CursorPosition--;

      strcpy(&Text[CursorPosition],&Text[CursorPosition+1]);
//      strcpy(&temp[CursorPosition+1],Text+CursorPosition);
//      strcpy(Text,temp);
    }
    Draw(0,0,a);
    goto a;
} else
if (VirtualKey==ESC) {
//  Screen->fill(row-1,column-1,row-1,column+length+1);
  return 0;
}
if (VirtualKey==CR) {
//        Screen->fill(row-1,column-1,row-1,column+length+1);
        return 1;
}


if (VirtualKey==c) {
  if (strlen(Text)==length) {
       Serial.print(7);
  } else {
    strncpy((char *)temp,(char *)Text,CursorPosition);
    temp[CursorPosition]=VirtualKey;
    strcpy((char *)&temp[CursorPosition+1],(char *)Text+CursorPosition);
    strcpy((char *)Text,(char *)temp);
    CursorPosition++;
  }
  Draw(0,0,a);
}




 VirtualKey=0;
 goto a;
}

 

Borland
Offline
Зарегистрирован: 17.05.2012

Ну и Slot.h

#ifndef MAXSLOTS
#define MAXSLOTS 10
#endif

#ifndef __BORLANDC__
  #include <inttypes.h>
#endif
//  #include <stdlib.h>
//  #include <string.h>
#include "Ansiterm.h"
//#include <avr/pgmspace.h>

#define LEFT 250
#define RIGHT 251
#define UP 252
#define DOWN 253
#define ESC 27
#define CR 13
#define CTRLCR 10
#define BACKSPACE 8
#define DELETE  127
#define CTRLX  0x18


//#define BORDERS 1
//char border [6][3] PROGMEM ={{0xDA,0xC4,0x3F,0xB3,0xC0,0xC0},
/*char border[] PROGMEM ={0xDA,0xC4,0x3F,0xB3,0xC0,0xC0,
			0xC9,0xCD,0xBB,0xBA,0xC8,0xBC,
	            	0xD5,0xCD,0xB8,0xB3,0xD4,0xBE
			 };
*/
#ifdef __BORLANDC__
#define uint8_t unsigned char
#endif
//#define  byte unsigned char

class stars {
   int magnitude;       // Data member
   int starfunc(void);  // Member function

};
char * justify(unsigned char c,unsigned char l,char *s,unsigned char b);

typedef struct Slot {


/*public:*/
	char Title[80];
	char Text[80];
        uint8_t  row;
	uint8_t column;
        unsigned char style;
// 1 1 1 1   1 1 1 1
//             ! ! !- Slot For Edit//Picture
//             ! ---- Border Type;
//

	unsigned char length; // lowest 7 bits;
	unsigned char color;
	unsigned char specialedit;
	
	int Edit(Slot *c);
        void (* SpecialEdit)(int b,Slot *a);
	Ansiterm *Screen;
        void Draw(uint8_t a,uint8_t b,Slot *c);
	void Before();
//
        unsigned char CursorPosition;

//        void preamble();
//        void preambleAndNumberAndValue(int x, char v);
//        void setAttribute(int a);
} Slot;

typedef struct  {
          char temp[80];
          Slot *Slots[MAXSLOTS];  // Defined By Generator
          void Draw(void);
          void Edit(void);
	  Ansiterm *Screen;
	} Frame;

typedef struct Menu {
	  char *Title;
          unsigned char style;
// 1 1 1 1   1 1 1 1 
//           ! ! ! !- Horisontal/Vertical
//           ! ! ---- Border Type;
//           ! ----  Offset ( no Border)

          unsigned char  row;
  	  uint8_t column;
	  unsigned char length;
	  unsigned char depth;
	  char **ItemsList;
	  uint8_t NumberOfItems;
       	  uint8_t FirstItem;
          uint8_t CurrentItem;
	  void Before(uint8_t CurItem);
          void After(uint8_t CurItem);

          uint8_t Run(uint8_t x, uint8_t y);
          Ansiterm *Screen;
	  void DrawItems(void);

	} Menu;

все слегка или даже не слегка недоделано, скажем хочу вызывать функции Before и After перехода к Itemу меню, ну и была мысль привязать класс AnsiTerm к элементам графики

 

pistoletov
Offline
Зарегистрирован: 15.08.2011

 будут вопросы - пишите-)))))))))

#include <LiquidCrystal.h>
#include <EEPROM.h>
#include "RotaryEncoder.h"
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>; // written by  mattt on the Arduino forum and modified by D. Sjunnesson
LiquidCrystal lcd(13, 12, 5, 4, 3, 2);
RotaryEncoder rotary(7, 6, 8);


int time_on_h = 3;
int time_on_m = 50;
int time_on_hleft = 5;
int time_on_mleft = 20;
int duration ;
int FLAG = 0;
int dayp = 1;
int durationleft;
int min_on;
int min_onleft;
int min_off;
int min_offleft;
int min_off_real;
int min_cur;
int min_cur_empty;
int min_cur_full;
int min_pause;
int empty = 0;
int WS =A1;
int poliv;
int i;
int showitem=1;
int new_pos;
const int PUMP = 11; //water pump on 11
const int VALVE1 = 9; //valve 1 on 9
const int VALVE2 = 10; //valve 2 on 10





void setup()
{
  Serial.begin(9600);
  

//  RTC.stop();
//  RTC.set(DS1307_SEC,05);        //set the seconds
//  RTC.set(DS1307_MIN,34);     //set the minutes
//  RTC.set(DS1307_HR,19);       //set the hours
//  RTC.set(DS1307_DOW,16);       //set the day of the week
//  RTC.set(DS1307_DATE,13);       //set the date
//  RTC.set(DS1307_MTH,8);        //set the month
//  RTC.set(DS1307_YR,11);         //set the year
//  RTC.start();
 
 
  
  lcd.begin(16, 2);
  pinMode(PUMP, OUTPUT);
  pinMode(VALVE1, OUTPUT);
  pinMode(VALVE2, OUTPUT);
  time_on_h=EEPROM.read(1);
  time_on_m=EEPROM.read(2);
  duration=EEPROM.read(3);
  time_on_hleft=EEPROM.read(4);
  time_on_mleft=EEPROM.read(5);
  durationleft=EEPROM.read(6);
  min_on = time_on_h*60 + time_on_m;
  min_off = min_on + duration;
  dayp=EEPROM.read(7);
  min_onleft = time_on_hleft*60 + time_on_mleft;
  min_offleft = min_onleft + durationleft;
  rotary.position(1);
  rotary.minimum(1);
  rotary.maximum(6);
  new_pos = 0;
  
}

void loop()

{ 
  
      if (new_pos != rotary.position() || (millis()%500 == 0 ) ) 
     { new_pos = rotary.position();
       showitem=rotary.position();
       Serial.println(showitem);
       lcdvisual(showitem);
     
     }
  
  
  


  
 // pdelay(3000);
  FLAG = 0;
  
  if (min_cur == min_on)
  
     {
       min_pause = 0;
     };

  while ((min_cur >= min_on) && (min_cur <= min_off + min_pause) && (poliv==0) ) 

  {  
    min_cur = RTC.get(DS1307_HR,true)*60 + RTC.get(DS1307_MIN,false);
    Serial.print("min_cur");
    Serial.print(min_cur);
    Serial.print("min_on");
    Serial.print(min_on);
    Serial.print("  min_off ");
    Serial.print(min_off+min_pause);
    lcd.clear(); 
    lcd.print("NOW watering");
    Serial.print("NOW watering");
   
    digitalWrite (VALVE1, HIGH);
    pdelay (2000);
    lcd.clear(); 
    lcd.print("PUMP ON");
    digitalWrite (PUMP, HIGH);
    pdelay(2000);
    lcd.clear();
    lcd.print("sensor=");
     lcd.print (analogRead (WS));
     pdelay (2000);
     lcd.clear();
       lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print ("Min ON:  ");
  lcd.print (min_on);

  lcd.setCursor(0, 1);
  lcd.print ("min_off  ");
  lcd.print (min_off+min_pause);
  pdelay (2000);
  lcd.clear();
    lcd.clear();

  lcd.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true
  lcd.print(":");  
  lcd.print(RTC.get(DS1307_MIN,false));//read minutes without update (false)
  lcd.print(":");
  lcd.print(RTC.get(DS1307_SEC,false));
 
  lcd.print(" ");                 // some space for a more happy life
  lcd.setCursor(0, 1);
  lcd.print(RTC.get(DS1307_DATE,false));//read date
  lcd.print("/");
  lcd.print(RTC.get(DS1307_MTH,false));//read month
  lcd.print("/");
  lcd.print(RTC.get(DS1307_YR,false)); //read year 
  lcd.setCursor (8,0);
  min_cur = RTC.get(DS1307_HR,false)*60 + RTC.get(DS1307_MIN,false);
    lcd.print ("mc: ");
  lcd.print (min_cur);
  pdelay(3000);
  lcd.clear();
    
   

    if ( (analogRead(WS) < 20 ) && (FLAG == 0))
         { lcd.clear(); 
           lcd.print("WATER EMPTY!!!!!");
           delay (2000);
           min_pause = pause();
         };  
    };
    
    
    
 while ((min_cur >= min_onleft) && (min_cur <= min_offleft + min_pause) && (poliv == 0) ) 

  {  
      min_cur = RTC.get(DS1307_HR,true)*60 + RTC.get(DS1307_MIN,false);
      Serial.print("min_cur");
      Serial.print(min_cur);
      Serial.print("min_on");
      Serial.print(min_on);
      Serial.print("  min_off ");
      Serial.print(min_off+min_pause);
      lcd.clear(); 
      lcd.print("NOW watering");
      Serial.print("NOW watering");
       digitalWrite (VALVE2, HIGH);
      delay (2000);
      lcd.clear(); 
      lcd.print("PUMP ON");
      digitalWrite (PUMP, HIGH);
      delay(2000);
      lcd.clear();
      lcd.print("sensor=");
       lcd.print (analogRead (WS));
       delay (2000);
       lcd.clear();
       lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print ("Min ON:  ");
      lcd.print (min_onleft);   

      lcd.setCursor(0, 1);
      lcd.print ("min_off  ");
    lcd.print (min_offleft+min_pause);
      delay (2000);

    lcd.clear();

  lcd.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true
  lcd.print(":");  
  lcd.print(RTC.get(DS1307_MIN,false));//read minutes without update (false)
  lcd.print(":");
  lcd.print(RTC.get(DS1307_SEC,false));
 
  lcd.print(" ");                 // some space for a more happy life
  lcd.setCursor(0, 1);
  lcd.print(RTC.get(DS1307_DATE,false));//read date
  lcd.print("/");
  lcd.print(RTC.get(DS1307_MTH,false));//read month
  lcd.print("/");
  lcd.print(RTC.get(DS1307_YR,false)); //read year 
  lcd.setCursor (8,0);
  min_cur = RTC.get(DS1307_HR,false)*60 + RTC.get(DS1307_MIN,false);
    lcd.print ("mc: ");
  lcd.print (min_cur);
  delay(3000);
  lcd.clear();
    
   

    if ( (analogRead(WS) < 20 ) && (FLAG == 0))
         { lcd.clear(); 
           lcd.print("WATER EMPTY!!!!!");
           delay (2000);
           min_pause = pause();
         };  
      
    
    

        
  };        
//lcd.clear();
//lcd.print("time pause = ");
//lcd.print (min_pause);
//delay (1000);
//lcd.clear();
//lcd.print ("time watering:");
//lcd.print (empty);
//delay (1000);
digitalWrite(PUMP,LOW);
digitalWrite(VALVE1,LOW);
digitalWrite(VALVE2,LOW);
    
} //loop       
   
  

   
  int   pause () {
  int pause = 0; 
  
  lcd.clear();
  lcd.print("func pause");
  delay (1000);
  digitalWrite (PUMP,LOW);
  delay(1000);
  digitalWrite (VALVE1,LOW);
  delay(1000);
  digitalWrite (VALVE2,LOW);
  min_cur_empty = RTC.get(DS1307_HR,true)*60 + RTC.get(DS1307_MIN,false);
  empty = min_cur_empty - min_on;
  lcd.clear();
  lcd.print ("time pause:");
  lcd.print (empty);
  delay (2000);
  lcd.clear();
  lcd.print ("min_cur_empty:");
  lcd.print (min_cur_empty);
  delay (1500);
  FLAG = 0;
  while (analogRead (WS) < 800 )
  {  lcd.clear(); 
     lcd.print("WAITING FILLING!!!!!");
     delay (2000);
     lcd.clear();
     if (rotary.pressed())
     {FLAG = 1;
     break;
     }
     lcd.print ("sensor=");
     lcd.print (analogRead (WS));
     delay (2000);
     lcd.clear();
  lcd.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true
  lcd.print(":");  
  lcd.print(RTC.get(DS1307_MIN,false));//read minutes without update (false)

  lcd.print(" ");                 // some space for a more happy life
  lcd.print(RTC.get(DS1307_DATE,false));//read date
  lcd.print("/");
  lcd.print(RTC.get(DS1307_MTH,false));//read month
  lcd.print("/");
  lcd.print(RTC.get(DS1307_YR,false)); //read year 
  delay(3000);
  // setting the new stop time
  min_cur_full = RTC.get(DS1307_HR,true)*60 + RTC.get(DS1307_MIN,false);
   min_pause = (min_cur_full-min_cur_empty);

  lcd.clear();
  lcd.print ("min_cfull ");
  lcd.print (min_cur_full);
  delay(1000);
   lcd.clear();
   lcd.setCursor(0, 1);
  lcd.print ("min_pause  ");
  lcd.print (min_pause);
  delay(1000);
  
  }     
     
  return min_pause;   
  }     
     
     


void  pdelay (int time)         
{ int data = 0;

for (int i=0; i<=time/10; i++) 
{
delay (10);
 if (rotary.pressed())
     {delay (500);
     if (rotary.pressed())
      { lcd.clear();
        sets();
      
      }
     
     }
}  
}            



 void sets ()
 
 
 {
 int rotcur;
  
 
 lcd.clear();
 lcd.print ("SETUP");
 while (rotary.pressed())
{ delay(10);
}
lcd.clear();
lcd.print ("Time start RIGHT");
lcd.setCursor(2,1);
lcd.print(":");
time_on_h=setdata(1,23,1,0,1);
EEPROM.write(1,time_on_h);
time_on_m=setdata(1,59,2,3,1);
EEPROM.write(2,time_on_m);
lcd.setCursor(7,1);
lcd.print("MINS:");
duration=setdata(1,99,3,12,1);
EEPROM.write(3,duration);
//part left times settings;

lcd.clear();
lcd.print ("Time start LEFT");
lcd.setCursor(2,1);
lcd.print(":");
time_on_hleft=setdata(1,23,4,0,1);
EEPROM.write(4,time_on_hleft);
time_on_mleft=setdata(1,59,5,3,1);
EEPROM.write(5,time_on_mleft);
lcd.setCursor(7,1);
lcd.print("MINS:");
durationleft=setdata(1,99,6,12,1);
EEPROM.write(6,duration);
//sets days watering
lcd.clear();
rotary.maximum(3);
rotary.minimum(1);
rotary.position(EEPROM.read(7));
rotcur=rotary.position();
lcd.print("SET WATERING DAYS");
while (rotary.pressed() == 0)
{

if (rotcur != rotary.position())
{  
rotcur=rotary.position();  
  
if (rotary.position() == 1)
   {lcd.clear();
    lcd.print("EVERY DAY WATERING");
   };

if (rotary.position() == 2)
   {lcd.clear();
    lcd.print("ONE DAY PAUSE");
      };    

if (rotary.position() == 3)
   {lcd.clear();
    lcd.print("TWO DAYS PAUSE");
      };
}
if (rotary.pressed())
{dayp=rotary.position();
 EEPROM.write(7,dayp);
 break;
}
}


lcd.clear();
lcd.print("DATA STORED");
rotary.position(showitem);
delay (500);



setup();

 }
      
  int setdata (int minval, int maxval, int mem, int pos,int pos2)
{
  int result = 0;
  int press = 0;
  String stringOne;
  rotary.minimum(minval);
  rotary.maximum(maxval);
  rotary.position(EEPROM.read(mem));
  while (rotary.pressed ())
  {delay(10);
  }
  
  while (press == 0)
{
 
  lcd.setCursor(pos, pos2);
   Serial.print(rotary.pressed()); 
  Serial.print(rotary.position()); 
  stringOne = String(rotary.position(), DEC);
  if ( (rotary.position()<10) && (rotary.position()>-1))
  {
  stringOne = ' ' + stringOne;
  }
  lcd.print(stringOne);
 ;
  
 
 if (rotary.pressed())
 { while (rotary.pressed())
   {delay(10);
   }
   
   result = rotary.position();
    Serial.print(stringOne);
    
    press = 1;

 }
 
 }
 
return result; 
 
   
  
}

void lcdvisual(int menu)
{ //ВЫВОДИМ НА ЭКРАНЧИК ИНФО ОТ ПОЛОЖЕНИЯ ЭНКОДЕРА
  Serial.println(menu);
  switch (menu)
  
  {
  
   case 1:  //выводим время
   lcd.clear();
   lcd.print(RTC.get(DS1307_HR,true)); //read the hour and also update all the values by pushing in true
  lcd.print(":");  
  lcd.print(RTC.get(DS1307_MIN,false));//read minutes without update (false)
  lcd.print(":");
  lcd.print(RTC.get(DS1307_SEC,false));
  lcd.print(" ");                 // some space for a more happy life
  lcd.setCursor(0, 1);
  lcd.print(RTC.get(DS1307_DATE,false));//read date
  lcd.print("/");
  lcd.print(RTC.get(DS1307_MTH,false));//read month
  lcd.print("/");
  lcd.print(RTC.get(DS1307_YR,false)); //read year 
  lcd.setCursor (9,0);
  min_cur = RTC.get(DS1307_HR,true)*60 + RTC.get(DS1307_MIN,false);
    lcd.print ("mc:");
  lcd.print (min_cur);
  poliv=RTC.get(DS1307_DATE,false) % dayp;
  lcd.setCursor(10,1);
  if (poliv==0)
  {
  lcd.print("Today");
  }
   
   
   break;  
   
  
   
   case 2:  //времф правого полива
    lcd.clear();
    lcd.print ("RIGHT  ON   OFF");
  lcd.setCursor(0, 1);

  lcd.print (min_on/60);
  lcd.print(":");
  lcd.print(min_on%60);
  lcd.setCursor(8, 1);

  lcd.print (min_off/60);
  lcd.print(":");;
  lcd.print(min_off%60);
    
    
    
    break;
   
   case 3: // ВРЕМЯ ЛЕВОГО ПОЛИВА
       lcd.clear();
    lcd.print ("LEFT ON   OFF");
  lcd.setCursor(0, 1);

  lcd.print (min_onleft/60);
  lcd.print(":");
  lcd.print(min_onleft%60);
  lcd.setCursor(8, 1);

  lcd.print (min_offleft/60);
  lcd.print(":");;
  lcd.print(min_offleft%60);
   
   break;
   
   case 4:
   lcd.clear();
   lcd.print("watering right");
   Serial.print(rotary.pressed());
    if (rotary.pressed())   {
      Serial.print("pressed");
      delay(500);
    }
    if (rotary.pressed())
    {
     while (rotary.pressed())  //wait untill unpressed
     { delay(10);
     } 
     lcd.clear(); 
     lcd.print("watering right");
     digitalWrite (VALVE1, HIGH);
    delay (500);
    lcd.clear(); 
    lcd.print("PUMP ON");
    digitalWrite (PUMP, HIGH);
    delay(1000);
    
     
    while(!rotary.pressed()) // пока не нажмется енкодер
    {delay(10);
      if (rotary.pressed())
         {delay(500);
         }
    }
         lcd.clear(); 
     lcd.print("watering stop");
     digitalWrite (VALVE1, LOW);
    delay (500);
    lcd.clear(); 
    lcd.print("PUMP OFF");
    digitalWrite (PUMP, LOW);
    delay(1000);
    }  
    
    
     
        
           
   //  ВКЛ ПРАВЫЙ 
   break;
   
   case 5:
   lcd.clear();
   lcd.print("watering left");
   Serial.print(rotary.pressed());
    if (rotary.pressed())   {
      Serial.print("pressed");
      delay(500);
    }
    if (rotary.pressed())
    {
     while (rotary.pressed())  //wait untill unpressed
     { delay(10);
     } 
     lcd.clear(); 
     lcd.print("Start");
     digitalWrite (VALVE2, HIGH);
    delay (1000);
    lcd.clear(); 
    lcd.print("PUMP ON");
    digitalWrite (PUMP, HIGH);
    delay(1000);
    
     
    while(!rotary.pressed()) // пока не нажмется енкодер
    {delay(10);
      if (rotary.pressed())
         {delay(500);
         }
    }
         lcd.clear(); 
     lcd.print("watering stop");
     digitalWrite (VALVE2, LOW);
    delay (1000);
    lcd.clear(); 
    lcd.print("PUMP OFF");
    digitalWrite (PUMP, LOW);
    delay(1000);
    }  
    
    
     
        
           
   
   //  ВКЛ ЛЕВЫЙ
   break;
   
   
   case 6: 
    lcd.clear();
   lcd.print("SETUP");
   if (rotary.pressed())
     {delay (500);
     if (rotary.pressed())
      { lcd.clear();
        sets(); //  УСТАНОВКИ
      }
   
     }break;
  }
}


    

  
  

 //loop;

 

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 Дык, с порога орёт 'RotaryEncoder' does not name a type

на 110 строку min_cur = RTC.get(DS1307_HR,true)*60 + RTC.get(DS1307_MIN,false);
 ругается 'RTC' was not declared in this scope

Библиотеку RotaryEncoder.h нашёл и положил в папку libraries.

#include <WProgram.h>  
исправил на
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

а вот что делать с последним сообщением, я не знаю...

 

pistoletov
Offline
Зарегистрирован: 15.08.2011

 скетч для 0022 версии написан. RTC это библиотека часов ds1307. библиотеку часов подключите или уберите тогда все функции работы с часами. В моем скетче все на часах завязано. 

pistoletov
Offline
Зарегистрирован: 15.08.2011

 Что делаете если не секрет - подскажу как бы я сделал.

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 Я сейчас обдумываю вариант для токарного станка. Суть, убрать гитару и поставить электродвигатели на винты подач. У каждого двигателя свой контроллер. Вместо ручек и рычагов выбора подач, думаю поставить энкодер. Arduino должен вывести на LCD информацию, какую подачу или шаг резьбы выставили и соответственно, подать на контроллер двигателя управляющий сигнал. По информации с энкодера на шпинделе и двигателе подач, Arduino должен корректировать сигнал управления для контроллера, чтобы обеспечить нарезание нужной резьбы или подачи. Вот, в общих чертах мой план. Можно реализовать такую идею на Arduino ?

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

Сейчас скачал и положил другую библиотеку DS1307.h теперь выдаёт, ошибка при компилляции:

C:\arduino-1.0.1\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -IC:\arduino-1.0.1\hardware\arduino\cores\arduino -IC:\arduino-1.0.1\hardware\arduino\variants\standard -IC:\arduino-1.0.1\libraries\LiquidCrystal -IC:\arduino-1.0.1\libraries\EEPROM -IC:\arduino-1.0.1\libraries\RotaryEncoder -IC:\arduino-1.0.1\libraries\Wire -IC:\arduino-1.0.1\libraries\DS1307 C:\DOCUME~1\PAPARI~1\LOCALS~1\Temp\build2078228489559218613.tmp\sketch_men__na_encodere_nerabotaet.cpp -o C:\DOCUME~1\PAPARI~1\LOCALS~1\Temp\build2078228489559218613.tmp\sketch_men__na_encodere_nerabotaet.cpp.o
sketch_men__na_encodere_nerabotaet.cpp:12:20: warning: extra tokens at end of #include directive
In file included from C:\arduino-1.0.1\libraries\DS1307/WConstants.h:1,
from C:\arduino-1.0.1\libraries\DS1307/DS1307.h:10,
from sketch_men__na_encodere_nerabotaet.cpp:12:
C:\arduino-1.0.1\libraries\DS1307/wiring.h:88:1: warning: "clockCyclesToMicroseconds" redefined
In file included from sketch_men__na_encodere_nerabotaet.cpp:6:
C:\arduino-1.0.1\hardware\arduino\cores\arduino/Arduino.h:77:1: warning: this is the location of the previous definition
In file included from C:\arduino-1.0.1\libraries\DS1307/WConstants.h:1,
from C:\arduino-1.0.1\libraries\DS1307/DS1307.h:10,
from sketch_men__na_encodere_nerabotaet.cpp:12:
C:\arduino-1.0.1\libraries\DS1307/wiring.h:89:1: warning: "microsecondsToClockCycles" redefined
In file included from sketch_men__na_encodere_nerabotaet.cpp:6:
C:\arduino-1.0.1\hardware\arduino\cores\arduino/Arduino.h:78:1: warning: this is the location of the previous definition
sketch_men__na_encodere_nerabotaet.cpp: In function 'int pause()':
sketch_men__na_encodere_nerabotaet.cpp:281: warning: unused variable 'pause'
sketch_men__na_encodere_nerabotaet.cpp: In function 'void pdelay(int)':
sketch_men__na_encodere_nerabotaet.cpp:352: warning: unused variable 'data'
C:\arduino-1.0.1\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -IC:\arduino-1.0.1\hardware\arduino\cores\arduino -IC:\arduino-1.0.1\hardware\arduino\variants\standard -IC:\arduino-1.0.1\libraries\LiquidCrystal -IC:\arduino-1.0.1\libraries\EEPROM -IC:\arduino-1.0.1\libraries\RotaryEncoder -IC:\arduino-1.0.1\libraries\Wire -IC:\arduino-1.0.1\libraries\DS1307 -IC:\arduino-1.0.1\libraries\LiquidCrystal\utility C:\arduino-1.0.1\libraries\LiquidCrystal\LiquidCrystal.cpp -o C:\DOCUME~1\PAPARI~1\LOCALS~1\Temp\build2078228489559218613.tmp\LiquidCrystal\LiquidCrystal.cpp.o
C:\arduino-1.0.1\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -IC:\arduino-1.0.1\hardware\arduino\cores\arduino -IC:\arduino-1.0.1\hardware\arduino\variants\standard -IC:\arduino-1.0.1\libraries\LiquidCrystal -IC:\arduino-1.0.1\libraries\EEPROM -IC:\arduino-1.0.1\libraries\RotaryEncoder -IC:\arduino-1.0.1\libraries\Wire -IC:\arduino-1.0.1\libraries\DS1307 -IC:\arduino-1.0.1\libraries\EEPROM\utility C:\arduino-1.0.1\libraries\EEPROM\EEPROM.cpp -o C:\DOCUME~1\PAPARI~1\LOCALS~1\Temp\build2078228489559218613.tmp\EEPROM\EEPROM.cpp.o
C:\arduino-1.0.1\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -IC:\arduino-1.0.1\hardware\arduino\cores\arduino -IC:\arduino-1.0.1\hardware\arduino\variants\standard -IC:\arduino-1.0.1\libraries\LiquidCrystal -IC:\arduino-1.0.1\libraries\EEPROM -IC:\arduino-1.0.1\libraries\RotaryEncoder -IC:\arduino-1.0.1\libraries\Wire -IC:\arduino-1.0.1\libraries\DS1307 -IC:\arduino-1.0.1\libraries\RotaryEncoder\utility C:\arduino-1.0.1\libraries\RotaryEncoder\RotaryEncoder.cpp -o C:\DOCUME~1\PAPARI~1\LOCALS~1\Temp\build2078228489559218613.tmp\RotaryEncoder\RotaryEncoder.cpp.o
C:\arduino-1.0.1\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -IC:\arduino-1.0.1\hardware\arduino\cores\arduino -IC:\arduino-1.0.1\hardware\arduino\variants\standard -IC:\arduino-1.0.1\libraries\LiquidCrystal -IC:\arduino-1.0.1\libraries\EEPROM -IC:\arduino-1.0.1\libraries\RotaryEncoder -IC:\arduino-1.0.1\libraries\Wire -IC:\arduino-1.0.1\libraries\DS1307 -IC:\arduino-1.0.1\libraries\Wire\utility C:\arduino-1.0.1\libraries\Wire\Wire.cpp -o C:\DOCUME~1\PAPARI~1\LOCALS~1\Temp\build2078228489559218613.tmp\Wire\Wire.cpp.o
C:\arduino-1.0.1\hardware\tools\avr\bin\avr-gcc -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -IC:\arduino-1.0.1\hardware\arduino\cores\arduino -IC:\arduino-1.0.1\hardware\arduino\variants\standard -IC:\arduino-1.0.1\libraries\LiquidCrystal -IC:\arduino-1.0.1\libraries\EEPROM -IC:\arduino-1.0.1\libraries\RotaryEncoder -IC:\arduino-1.0.1\libraries\Wire -IC:\arduino-1.0.1\libraries\DS1307 -IC:\arduino-1.0.1\libraries\Wire\utility C:\arduino-1.0.1\libraries\Wire\utility\twi.c -o C:\DOCUME~1\PAPARI~1\LOCALS~1\Temp\build2078228489559218613.tmp\Wire\utility\twi.c.o
C:\arduino-1.0.1\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=101 -IC:\arduino-1.0.1\hardware\arduino\cores\arduino -IC:\arduino-1.0.1\hardware\arduino\variants\standard -IC:\arduino-1.0.1\libraries\LiquidCrystal -IC:\arduino-1.0.1\libraries\EEPROM -IC:\arduino-1.0.1\libraries\RotaryEncoder -IC:\arduino-1.0.1\libraries\Wire -IC:\arduino-1.0.1\libraries\DS1307 -IC:\arduino-1.0.1\libraries\DS1307\utility C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp -o C:\DOCUME~1\PAPARI~1\LOCALS~1\Temp\build2078228489559218613.tmp\DS1307\DS1307.cpp.o
In file included from C:\arduino-1.0.1\hardware\arduino\cores\arduino/Print.h:26,
from C:\arduino-1.0.1\hardware\arduino\cores\arduino/Stream.h:26,
from C:\arduino-1.0.1\libraries\LiquidCrystal/../Wire/Wire.h:26,
from C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp:2:
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:116: error: declaration of C function 'StringSumHelper& operator+(const StringSumHelper&, const char*)' conflicts with
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:115: error: previous declaration 'StringSumHelper& operator+(const StringSumHelper&, const String&)' here
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:116: warning: 'StringSumHelper& operator+(const StringSumHelper&, const char*)' is already a friend of class 'String'
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:117: error: declaration of C function 'StringSumHelper& operator+(const StringSumHelper&, char)' conflicts with
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:116: error: previous declaration 'StringSumHelper& operator+(const StringSumHelper&, const char*)' here
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:117: warning: 'StringSumHelper& operator+(const StringSumHelper&, char)' is already a friend of class 'String'
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:118: error: declaration of C function 'StringSumHelper& operator+(const StringSumHelper&, unsigned char)' conflicts with
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:117: error: previous declaration 'StringSumHelper& operator+(const StringSumHelper&, char)' here
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:118: warning: 'StringSumHelper& operator+(const StringSumHelper&, unsigned char)' is already a friend of class 'String'
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:119: error: declaration of C function 'StringSumHelper& operator+(const StringSumHelper&, int)' conflicts with
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:118: error: previous declaration 'StringSumHelper& operator+(const StringSumHelper&, unsigned char)' here
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:119: warning: 'StringSumHelper& operator+(const StringSumHelper&, int)' is already a friend of class 'String'
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:120: error: declaration of C function 'StringSumHelper& operator+(const StringSumHelper&, unsigned int)' conflicts with
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:119: error: previous declaration 'StringSumHelper& operator+(const StringSumHelper&, int)' here
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:120: warning: 'StringSumHelper& operator+(const StringSumHelper&, unsigned int)' is already a friend of class 'String'
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:121: error: declaration of C function 'StringSumHelper& operator+(const StringSumHelper&, long int)' conflicts with
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:120: error: previous declaration 'StringSumHelper& operator+(const StringSumHelper&, unsigned int)' here
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:121: warning: 'StringSumHelper& operator+(const StringSumHelper&, long int)' is already a friend of class 'String'
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:122: error: declaration of C function 'StringSumHelper& operator+(const StringSumHelper&, long unsigned int)' conflicts with
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:121: error: previous declaration 'StringSumHelper& operator+(const StringSumHelper&, long int)' here
C:\arduino-1.0.1\hardware\arduino\cores\arduino/WString.h:122: warning: 'StringSumHelper& operator+(const StringSumHelper&, long unsigned int)' is already a friend of class 'String'
C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp: In member function 'void DS1307::read()':
C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp:22: error: 'class TwoWire' has no member named 'send'
C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp:30: error: 'class TwoWire' has no member named 'receive'
C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp: In member function 'void DS1307::save()':
C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp:38: error: 'class TwoWire' has no member named 'send'
C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp:41: error: 'class TwoWire' has no member named 'send'
C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp: In member function 'void DS1307::set(int, int)':
C:\arduino-1.0.1\libraries\DS1307\DS1307.cpp:104: warning: suggest parentheses around arithmetic in operand of |

мне самому, в этом не разобраться...

 

pistoletov
Offline
Зарегистрирован: 15.08.2011

 конечно можно такое реализовать я думаю вам проще всего будет взять библиотеку энкодера и поиграться просто с ней без моего "лишнего кода" и поиграться с библиотекой шагового двигателя. ПРоблема думаю что именно мой софт написан для 0022 версии. ПО свободе попробую его компильнуть в 1.0

 

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 Нет, двигатель будет серво. Играться можно, когда понимаешь, а я не программист... Я пробовал Ваш скетч и в 0022 и в последней, одинаково. У меня проблема была в два этапа, сначала не находила WConstants.h, положил, потом не находила wiring.h, положил, а теперь я не понимаю, что там...

Покажите пожалуйста, как убрать или отключить, часы в Вашем скетче.

pistoletov
Offline
Зарегистрирован: 15.08.2011

 серво?  хм - насколько я знаю сервы осуществляют поворот на определенный угол, даже полного оборота не делают - я же понимаю что вам нужно давать вращение винту...мой скетч как образец не совсем то, что вам нужно. В библиотеке енкодера есть примеры его работы - file-examples-rotary encoder там посмотрите скетч работы энкодера.

mat
mat аватар
Offline
Зарегистрирован: 05.07.2012

 Есть серво для промышленных целей, там крутит так, как нам нужно. Это коллекторный ( у меня ) двигатель и на валу у него закреплён энкодер. По энкодеру контроллер определяет положение вала и управляет им.

Да, конечно, я понимаю что этот скетч не то, что мне нужно но, мне хотя бы понять, как программировать. А то, в инете нашёл разные статьи но, там ошибки и в схеме, и в программе... В итоге, ни что не работает и ни чему не научишься. Вот и решил, здесь попросить помощи. Пока не отказывают и на том спасибо.

NE_XT
NE_XT аватар
Offline
Зарегистрирован: 22.05.2012

Подниму тему, не создавая новую, так как она  актуальна для меня сейчас,

толи старею, толи много пива иногда бывает, понадобился пример простейшего меню с энкодером для регулировки температуры

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

нужно иметь следующее в скетче иметь возможность прописать температуру минимум-максимум, также прописать шаг изменения..

энкодером выставлять нужное значение и нажатием  фиксировать его....

Индикация не важна будь то лсд или сегментная матрица.. датчики и силовая часть уже не трудно...

Если кто знает готовое решение ,  ответьте плз..

 

 

aleksjetav
Offline
Зарегистрирован: 23.11.2012

Помгите с меню. ничего не могу разобрать не очень шарю в английском собрал часы с измереением влажности и температуры, хочу сделать меню что бы параметры были регулируемыми и еще включалась нагрузка одна по времени, а две других в зависимости от влажности и температуры 

буду рад советам 

dzmitry
Offline
Зарегистрирован: 12.08.2012

Мне поравилась вот эта http://easyelectronics.ru/organizaciya-drevovidnogo-menyu.html статья.

vworld
vworld аватар
Offline
Зарегистрирован: 26.09.2011

pistoletov пишет:

В библиотеке енкодера есть примеры его работы - file-examples-rotary encoder там посмотрите скетч работы энкодера.

подскажите, а какую модель энкодера с кнопкой вы использовали в своем примере?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Я для себя первый раз так делал


//Пример простого меню для Arduino
//В меню используется 4 экрана
//за номер отображаемого экрана отвечает переменная m
#include <LiquidCrystal.h> //Библиотека LCD
// инициализация LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int m=0; //переменная для экранов меню
int p1=0; // переменная для примера 1
int p2=0; // -//- 2
int p3=0; // -//- 3

byte nextPin = 6; //кнопка меню на 6 входе
byte prevPin = 7; //кнопка возврата 
byte upPin = 9; //увеличение значения отображаемого параметра
byte downPin = 10;//уменьшение значения
byte ledPin =13;//Светодиод

void setup() {
  //Установка пинов как входов
  pinMode(nextPin, INPUT);
  pinMode(prevPin, INPUT);
  pinMode(upPin, INPUT);
  pinMode(downPin, INPUT);
  
  pinMode(ledPin, OUTPUT);
  //Установка количества столбцов и строк дисплея
  lcd.begin(16, 2);
  // Вывод приветствия
  lcd.print("DEMO MENU!");
  // задержка
  delay (500);
}

void loop() {
  //Обработка нажатия кнопки меню
  if (digitalRead(nextPin)== HIGH)
  {
  m++;//увеличиваем переменную уровня меню
  if (m>3)//если уровень больше 3
  {
  m=0;// то вернуться к началу
  }
  delay (100);
  lcd.clear();
  }
  //Обработка нажатия кнопки назад
  if (digitalRead(prevPin)== HIGH)
  {
  m--;
  if (m<0)
  {
  m=3;
  }
  delay (100);
  lcd.clear();
  }
  
  //Обработка нажатия для р1 +
    if (digitalRead(upPin)== HIGH && m==1)//если находимся на экране с переменной р1
  {
  p1++;//то при нажатии кнопки + увеличиваем переменную р1 на единицу
  if (p1>10)//если переменная достигла придела в 10 едениц
  {
  p1=0;//то возвращаем ее к 0
  }
  delay (100);
  lcd.clear();
  }
  //+ для р2
    if (digitalRead(upPin)== HIGH && m==2)
  {
  p2++;
  if (p2>10)
  {
  p2=0;
  }
  delay (100);
  lcd.clear();
  }
    //+ для р3
    if (digitalRead(upPin)== HIGH && m==3)
  {
  p3++;
  if (p3>1)
  {
  p3=0;
  }
  delay (100);
  lcd.clear();
  digitalWrite(ledPin, p3);
  }
  //сдесь код для уменьшения значений
  //аналогичен коду увеличения
  
  //вывод меню
  if (m==0)
  {
  lcd.setCursor(0, 0);
  lcd.print("Main Menu");
  lcd.setCursor(0, 1);
  lcd.print("P1=");
  lcd.print(p1);
  lcd.print(" P2=");
  lcd.print(p2);
  lcd.print(" LED=");
  lcd.print(p3);
  } 
  else if (m==1)
  {
  lcd.setCursor(0, 0);
  lcd.print("Parametr-1");
  lcd.setCursor(0, 1);
  lcd.print("P1 = ");
  lcd.print(p1);
  }
  
 else if (m==2)
  {
  lcd.setCursor(0, 0);
  lcd.print("Parametr-2");
  lcd.setCursor(0, 1);
  lcd.print("P2 = ");
  lcd.print(p2);
  }
 else if (m==3)
  {
  lcd.setCursor(0, 0);
  lcd.print("LED Control");
  lcd.setCursor(0, 1);
  lcd.print("LED = ");
  lcd.print(p3);
  }
//yul-i-an@gmail.com форум allduino.forum2x2.ru
}

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Версия кода с автовозвратом к основному скрину через 3 секунды

//Пример простого меню для Arduino
//В меню используется 4 экрана
//за номер отображаемого экрана отвечает переменная m
//Значения переменных р1,р2 меняются циклически от 0-10 затем опять 0, р3(LED) только 0 или 1 

#include <LiquidCrystal.h> //Библиотека LCD
// инициализация LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int m=0; //переменная для экранов меню
int p1=0; // переменная для переменной 1
int p2=0; // -//- 2
int p3=0; // -//- 3

byte nextPin = 6; //кнопка NEXT на 6 входе
byte prevPin = 7; //кнопка PREV
byte upPin = 9; //увеличение значения (UP) отображаемого параметра
byte downPin = 10; //уменьшение значения (DOWN)
byte ledPin =13; //Светодиод (исполнительное устройство)

long previousMillis = 0; //счетчик прошедшего времени для AutoMainScreen
long interval = 3000; //задержка автовозврата к MainScreen 3сек

void setup() {
  //Настройка входов
  pinMode(nextPin, INPUT);
  pinMode(prevPin, INPUT);
  pinMode(upPin, INPUT);
  pinMode(downPin, INPUT);
  //Настройка выходов
  pinMode(ledPin, OUTPUT);
  //Настройка дисплея
  //Установка количества столбцов и строк дисплея
  lcd.begin(16, 2);
  // Вывод приветствия при включении питания если нужно
  lcd.setCursor(3, 0);
  lcd.print("DEMO MENU");
  delay (300);//Задержка приветствия
}

void loop() {
  unsigned long currentMillis = millis();
  //Обработка нажатия кнопки NEXT
  if (digitalRead(nextPin)== HIGH)
  {
  m++;//увеличиваем переменную уровня меню
  previousMillis = currentMillis; //если кнопка была нажата сбросить счетчик автовозврата к главному экрану
  delay (100);
  //lcd.clear();
  if (m>3)//если уровень больше 3
  {
  m=0;// то вернуться к началу
  }
  }
  //Обработка нажатия кнопки PREV
  if (digitalRead(prevPin)== HIGH)
  {
  m--;
  previousMillis = currentMillis;
  delay (100);
  //lcd.clear();
  if (m<0)
  {
  m=3;
  }
  }
  
  //Обработка нажатия UP для р1
    if (digitalRead(upPin)== HIGH && m==1)//если находимся на экране с переменной р1
  {
  p1++;      //то при нажатии кнопки + увеличиваем переменную р1 на единицу
  previousMillis = currentMillis;
  delay (100);
  //lcd.clear();
  if (p1>10) //устанавливаем придел изменения переменной = 10
  {          //если больше предела
  p1=0;      //то возвращаем ее к 0 (тут код условия что делать при достижении приделов)
  }
  }
  //UP для р2
    if (digitalRead(upPin)== HIGH && m==2)
  {
  p2++;
  previousMillis = currentMillis;
  delay (100);
  //lcd.clear();
  if (p2>10)
  {
  p2=0;
  }
  }
    //UP для р3
    if (digitalRead(upPin)== HIGH && m==3)
  {
  p3++;
  previousMillis = currentMillis;
  delay (100);
  //lcd.clear();
  if (p3>1)
  {
  p3=0;
  }
  digitalWrite(ledPin, p3);
  }
  //сдесь код для уменьшения значений
  //аналогичен коду увеличения если нужно
  
  //Вывод меню
  //Описание экранов меню
  lcd.clear();
  if (m==0)                 //переменная m=0
  {                         //отображаем
  lcd.setCursor(3, 0);      //******************* 
  lcd.print("Main Screen"); //*Main Screen      *
  lcd.setCursor(0, 1);      //*P1=p1 P2=p2 LED=0*
  lcd.print("P1=");         //*******************    
  lcd.print(p1);
  lcd.print(" P2=");
  lcd.print(p2);
  lcd.print(" LED=");
  lcd.print(p3);
  } 
  else if (m==1)            //переменная m=1
  {                         //отображаем
  lcd.setCursor(0, 0);      //*******************
  lcd.print("Parametr-1");  //*Parametr-1       *
  lcd.setCursor(0, 1);      //*P1=p1            *
  lcd.print("P1 = ");       //*******************
  lcd.print(p1);
  }
 else if (m==2)             //переменная m=2
  {                         //отображаем
  lcd.setCursor(0, 0);      //*******************
  lcd.print("Parametr-2");  //*Parametr-2       *
  lcd.setCursor(0, 1);      //*P2=p2            *
  lcd.print("P2 = ");       //*******************
  lcd.print(p2);
  }
 else if (m==3)             //переменная m=3
  {                         //отображаем
  lcd.setCursor(0, 0);      //*******************
  lcd.print("LED Control"); //LED Control       *
  lcd.setCursor(0, 1);      //LED = p3          *
  lcd.print("LED = ");      //*******************
  lcd.print(p3);
  }
  //Проверка автовозврата
  if(currentMillis - previousMillis > interval)  //Если счетчик
  {
    previousMillis = currentMillis;              //достиг интервала 
    m=0;                                         //то отобразить главный экран
    //lcd.clear();
  }
//yul-i-an@gmail.com форум allduino.forum2x2.ru
}

 

NE_XT
NE_XT аватар
Offline
Зарегистрирован: 22.05.2012

yul-i-an ,

Спасиб..

Чудненько, ....  будет чем занятся на выходных.

Может и на 3.2 TFT дисплей есть пример, с энкодером ?

;)

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Радует что комуто полезно оказалось. С энкодером попробую на днях.

С энкодером нужно работать c внешними прерываниями.

Например выход энкодера А вешаем на INT0. Когда происходит событие этого прерывания проверяем состояние В выхода энкодера, если на А и В 1 то значит крутиться в одну сторону, а если на А 1, а на В 0 то в другую. Кнопочку энкодера можно повесить на прерывание INT1 чтоб всё четко отрабатывало.

leshak
Offline
Зарегистрирован: 29.09.2011

yul-i-an пишет:

Например выход энкодера А вешаем на INT0. Когда происходит событие этого прерывания проверяем состояние В выхода энкодера, если на А и В 1 то значит крутиться в одну сторону, а если на А 1, а на В 0 то в другую. Кнопочку энкодера можно повесить на прерывание INT1 чтоб всё четко отрабатывало.

В теории все просто, на практике - попил крови :) Нюанс есть еще в том что ловить Front или Back сигнала. В теории - без разницы, на практике - энкодер шумит и разница есть.

Вот эта ветка может пригодится http://arduino.ru/forum/apparatnye-voprosy/ispolzuem-enkoder?page=1

Там таки и основательно мы  ему кости перемыли ;)

djominov
Offline
Зарегистрирован: 23.09.2013

А вы не могли бы посоветовать, что надо сделать, чтобы экран не мерцал? Я так понимаю дело в том, что он слишком часто перерисовывается, вопрос в том, нужно ли это и так часто.

В остальном - хочу сказать огромное спасибо, за приятную и простую менюшку, как раз то, что искал.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Чтобы немерцал экран я думаю надо отчищать его не перед выбором выводимого экрана, а после того как выбран экран для вывода на дисплей. В начале каждого "экрана" после команды if нужно добавить строку lcd.clear(), и убрать её от туда где она сейчас стоит.

Сам непроверял но возможно поможет. Или можно отчищать экран только при изменении выводимой информации и позиции в меню.

Например если переменная m прошлая не равна m прошлой то отчистить экран, а если нет то идти дальше.

Тоже самое и с параметрами, если их значения изменились, то отчистить экран, а лучше не отчищать а по верх выводить.

mummykbf
Offline
Зарегистрирован: 28.03.2014

Спасибо yul-i-an за его вариант меню. очень понравилось. доступно и просто.

собрал схему, залил скеч и попробовал. меню работает, но захотелось кое-что исправить:

1. экраны меню и параметры р1, р2 и р3 циклически менялись до тех пор, пока не отпустишь кнопку. частенько параметры перескакивали на 2-3 единицы за одно нажатие, это же применио и к смене экранов меню.

2. при увеличении\уменьшении параметров происходило мерцание (перерисовка) всего экрана.

3. при задании параметров р1 и р2 величной 10 не умещается значение 1 или 0 параметра LED, но тут уже ограничения по символам самого дисплея.

посидел вчера-сегодня и подправил под свои нужды, результатом доволен как слон. теперь переход между экранами меню и смена параметров происходит по отпусканию кнопки и параметр меняется строго на единицу; мерцания экрана при задании параметра не происходит.

для тех кто будет использовать в своих целях прошу обратить внимание - дисплей подключен по I2C .

 

//Пример простого меню для Arduino
//В меню используется 4 экрана
//за номер отображаемого экрана отвечает переменная m

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  //инициализируем 2х строчный дисплей

int m=0; // переменная для экранов меню
int p1=0; // переменная для примера 1
int p2=0; // переменная для примера 2
int p3=0; // переменная для примера 3

#define nextPin 6 // кнопка меню на 6 входе
#define prevPin 7 // кнопка возврата
#define upPin 9 // увеличение значения отображаемого параметра
#define downPin 10 // уменьшение значения
#define ledPin 13 // Светодиод

boolean buttonnextWasUp = true;
boolean buttonprevWasUp = true;
boolean buttonupWasUp = true;
boolean buttondownWasUp = true;

boolean ledEnabled = false;

void setup()
{

// Установка пинов как входов

pinMode(nextPin, INPUT);
pinMode(prevPin, INPUT);
pinMode(upPin, INPUT);
pinMode(downPin, INPUT);

pinMode(ledPin, OUTPUT);



lcd.init();			// инициализация LCD
lcd.backlight();		// включаем подсветку

// Вывод приветствия
lcd.print( "DEMO MENU!" );
// задержка
delay (500);
}


void loop ()
{
  boolean buttonnextIsUp = digitalRead(nextPin);
  boolean buttonprevIsUp = digitalRead(prevPin);
  boolean buttonupIsUp = digitalRead(upPin);
  boolean buttondownIsUp = digitalRead(downPin);
  
//Обработка нажатия кнопки меню
if (buttonnextWasUp && !buttonnextIsUp)
{
delay(10);
buttonnextIsUp = digitalRead(nextPin); 
if (!buttonnextIsUp)
{
m++;
if (m>3) 
{
m=0; 
}
delay(100);
lcd.clear();
}
}

//Обработка нажатия кнопки назад
if (buttonprevWasUp && !buttonprevIsUp)
{
delay(10);
buttonprevIsUp = digitalRead(prevPin); 
if (!buttonprevIsUp)
{
m--;
if (m<0) 
{
m=3; 
}
delay(100);
lcd.clear();
}
}


// Обработка нажатия для р1 +
if (buttonupWasUp && !buttonupIsUp)
{
delay(10);
buttonupIsUp = digitalRead(upPin); 
if (!buttonupIsUp && m==1)
{
p1++;
if (p1>10) 
{
p1=0; 
}
delay (100);
lcd.setCursor(5, 1);
lcd.print("  ");
}
}


// Обработка нажатия для р1 -
if (buttondownWasUp && !buttondownIsUp)
{
delay(10);
buttondownIsUp = digitalRead(downPin); 
if (!buttondownIsUp && m==1)
{
p1--;
if (p1<0)
{
p1=10;
}
delay (100);
lcd.setCursor(5, 1);
lcd.print("  ");
}
}


// Обработка нажатия для р2 +
if (buttonupWasUp && !buttonupIsUp)
{
delay(10);
buttonupIsUp = digitalRead(upPin); 
if (!buttonupIsUp && m==2)
{
p2++;
if (p2>10) 
{
p2=0; 
}
delay (100);
lcd.setCursor(5, 1);
lcd.print("  ");
}
}

// Обработка нажатия для р2 -
if (buttondownWasUp && !buttondownIsUp)
{
delay(10);
buttondownIsUp = digitalRead(downPin); 
if (!buttondownIsUp && m==2)
{
p2--;
if (p2<0)
{
p2=10;
}
delay (100);
lcd.setCursor(5, 1);
lcd.print("  ");
}
}

// Обработка нажатия для р3 +
if (buttonupWasUp && !buttonupIsUp)
{
delay(10);
buttonupIsUp = digitalRead(upPin); 
if (!buttonupIsUp && m==3)
{
  ledEnabled = !ledEnabled;
  digitalWrite(ledPin, ledEnabled);
  p3 = ledEnabled;
}
}


// Обработка нажатия для р3 -
if (buttondownWasUp && !buttondownIsUp)
{
delay(10);
buttondownIsUp = digitalRead(downPin); 
if (!buttondownIsUp && m==3)
{
  ledEnabled = !ledEnabled;
  digitalWrite(ledPin, ledEnabled);
  p3 = ledEnabled;
}
}


//вывод меню

if (m==0)
{
lcd.setCursor(0, 0);
lcd.print( "Main Menu" );
lcd.setCursor(0, 1);
lcd.print( "P1=" );
lcd.print(p1);
lcd.print( " P2=" );
lcd.print(p2);
lcd.print( " LED=" );
lcd.print(p3);
}
else if (m==1)
{
lcd.setCursor(0, 0);
lcd.print( "Parametr-1" );
lcd.setCursor(0, 1);
lcd.print( "P1 = " );
lcd.print(p1);
}
else if (m==2)
{
lcd.setCursor(0, 0);
lcd.print( "Parametr-2" );
lcd.setCursor(0, 1);
lcd.print( "P2 = " );
lcd.print(p2);
}
else if (m==3)
{

lcd.setCursor(0, 0);
lcd.print( "LED Control" );
lcd.setCursor(0, 1);
lcd.print( "LED = " );
lcd.print(p3);
}

buttonupWasUp = buttonupIsUp;
buttondownWasUp = buttondownIsUp;
buttonnextWasUp = buttonnextIsUp;
buttonprevWasUp = buttonprevIsUp;

}

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Незачто. Я сам на железе не проверял (до создания устройства дело не дошло), тестировал в протеусе. Рад что моя концепция оказалась простой и понятной.

Можно обработку нажатия кнопок и вывод меню оформить в виде функций (вызывать функцию обработки нажатий по прерыванию от кнопок), в вызваной функции после нажатия кнопки и изменения параметра вызывать функцию вывода экрана меню, а после вывода вернуться в основной цикл, это должно несколько ускорить работу этого кода и ускорить основной цикл.

Или каждый экран меню оформить в виде функции и вызывать только нужный экран, а не перебирать все. И код станет более удобным для добавления новых окон.