Форум обсуждения систем  

Вернуться   Форум обсуждения систем "Умный дом", проектов Ардуино, OpenWRT и других DIY устройств > Форум умного дома > Сделай сам > Интерфейсы

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 14.05.2015, 03:15   #1
stD
Senior Member
 
Аватар для stD
 
Регистрация: 02.04.2012
Адрес: Питер
Сообщений: 1,125
Вес репутации: 1311
stD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant futurestD has a brilliant future
По умолчанию Шаблон интерфейса - плавное регулирование света и запись в EEPROM



Это тема - продолжение написаного тут.

Речь пойдёт о плавном регулировании освещения (диммер, далее ШИМ), а так же о сохранении значений в энергонезависимую память EEPROM.

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

Посмотреть-потрогать можно тут.

Видео:
http://www.youtube.com/watch?v=JakPclwfT7I

Кнопки будут включать/отключать соответствующие пины, а двиганье ползунками будет увеличивать/уменьшать ШИМ на D5 и D6.

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

Ардуино

Вначале обнулим EEPROM. Залейте этот скетч:

PHP код:
#include <EEPROM.h>

void setup()
{
  
// write a 0 to all 512 bytes of the EEPROM
  
for (int i 0512i++)
    
EEPROM.write(i0);

  
// turn the LED on when we're done
  
digitalWrite(13HIGH);
}

void loop()
{

Теперь основной скетч:

PHP код:
#include <EEPROM.h>

byte d2 EEPROM.read(2);     // флаги (состояние пинов) хранится в EEPROM, считываем их
byte d3 EEPROM.read(3);
byte d4 EEPROM.read(4);
int shim1 EEPROM.read(5); // значение ШИМ хранится в EEPROM, считываем их
int shim2 EEPROM.read(6);
byte d11 EEPROM.read(11);
byte d12 EEPROM.read(12);
byte d13 EEPROM.read(13);

byte descript[5]; // массив

void setup() 
{
  
Serial.begin(57600);
  
pinMode(2OUTPUT); 
  
pinMode(3OUTPUT);
  
pinMode(4OUTPUT);
  
pinMode(5OUTPUT);
  
pinMode(6OUTPUT);
  
pinMode(11OUTPUT);
  
pinMode(12OUTPUT);
  
pinMode(13OUTPUT);
  
  if(
d2digitalWrite(2HIGH); else digitalWrite(2LOW); // если до перезагрузки d2 была включена, то включаем, если нет, то нет 
  
delay(500); // чтобы не включалось всё сразу, делаем паузы
  
if(d3digitalWrite(3HIGH); else digitalWrite(3LOW);
  
delay(500);
  if(
d4digitalWrite(4HIGH); else digitalWrite(4LOW);
  
delay(500);
  
analogWrite(5shim1 2.55); // включаем ШИМ d5
  
delay(500);
  
analogWrite(6shim2 2.55); // включаем ШИМ d6
  
delay(500);
  if(
d11digitalWrite(11HIGH); else digitalWrite(11LOW);
  
delay(500);
  if(
d12digitalWrite(12HIGH); else digitalWrite(12LOW);
  
delay(500);
  if(
d13digitalWrite(13HIGH); else digitalWrite(13LOW);
}
  
void loop() 
{  
  if (
Serial.available()>4// ждём дескриптор и нужный символ
   
{
    if (
Serial.read()=='Y'// проверяем первый символ, если это 'Y', то продолжаем принимать, если нет, то выходим из цикла чтения
     
{
      for (
byte i=05i++)
        {
           
descript[i] = Serial.read(); // добавляем символы в массив   
        

        
    if((
descript[0] =='+') && (descript[1] =='=') && (descript[2] =='Z')) // проверяем дескриптор
     
{
      switch (
descript[3])
       {
         case 
'o'// обновление
         
glavnaia(); // отправка ответа
         
break;
         
         case 
'A'// d2 вкл
         
digitalWrite(2HIGH); // вкл d2
         
d2 1// ставим флаг в единицу (вкл)
         
EEPROM.write(2d2); // записываем состояние d2 в ячейку №2 EEPROM 
         
glavnaia(); // отправка ответа
         
break;
         
         case 
'a'// d2 откл
         
digitalWrite(2LOW); // откл d2
         
d2 0// ставим флаг в ноль (откл)
         
EEPROM.write(2d2); // записываем состояние d2 в ячейку №2 EEPROM 
         
glavnaia(); // отправка ответа
         
break; 
 
         case 
'B'// d3
         
digitalWrite(3HIGH);
         
d3 1;
         
EEPROM.write(3d3);
         
glavnaia();
         break;
         
         case 
'b'// d3
         
digitalWrite(3LOW);
         
d3 0;
         
EEPROM.write(3d3);
         
glavnaia();
         break;          
  
         case 
'C'// d4
         
digitalWrite(4HIGH);
         
d4 1;
         
EEPROM.write(4d4);
         
glavnaia();
         break;
         
         case 
'c'// d4
         
digitalWrite(4LOW);
         
d4 0;
         
EEPROM.write(4d4);
         
glavnaia();
         break;   
  
         case 
'D'// d5 прибавляем shim1
         
shim1++; // прибавляем
         
if(shim1 100shim1 100;  // если больше ста, то будет сто
         
EEPROM.write(5shim1); // записываем значение в ячейку №5 EEPROM 
         
analogWrite(5shim1 2.55); // включаем ШИМ D5 
         
glavnaia(); // функция отправки ответа
         
break;
         
         case 
'd'// d5 убавляем shim1
         
shim1--;
         if(
shim1 1shim1 0;
         
EEPROM.write(5shim1);
         
analogWrite(5shim1 2.55);
         
glavnaia();
         break; 
  
         case 
'E'// d6 прибавляем shim2
         
shim2++;
         if(
shim2 100shim2 100;
         
EEPROM.write(6shim2);
         
analogWrite(6shim2 2.55);
         
glavnaia();
         break;
         
         case 
'e'// d6 убавляем shim2
         
shim2--;
         if(
shim2 1shim2 0;
         
EEPROM.write(6shim2);
         
analogWrite(6shim2 2.55);
         
glavnaia();
         break;   
  
         case 
'F'// мгновенное включение ШИМ на D5
         
shim1 EEPROM.read(5); // считываем значение ШИМ из EEPROM
         
analogWrite(5shim1 2.55); // включаем ШИМ D5
         
glavnaia();
         break;
         
         case 
'f'// мгновенное отключение ШИМ на D5
         
shim1 0;
         
analogWrite(5shim1); // отключаем ШИМ D5, но НЕ записываем в EEPROM
         
glavnaia();
         break;  
 
         case 
'G'// мгновенное включение ШИМ на D6
         
shim2 EEPROM.read(6); // считываем значение ШИМ из EEPROM
         
analogWrite(6shim2 2.55); // включаем ШИМ D6
         
glavnaia();
         break;
         
         case 
'g'// мгновенное отключение ШИМ на D6
         
shim2 0;
         
analogWrite(6shim2); // отключаем ШИМ D6, но НЕ записываем в EEPROM
         
glavnaia();
         break;  
 
         case 
'J'// d11
         
digitalWrite(11HIGH);
         
d11 1;
         
EEPROM.write(11d11);
         
glavnaia();
         break;
         
         case 
'j'// d11
         
digitalWrite(11LOW);
         
d11 0;
         
EEPROM.write(11d11);
         
glavnaia();
         break;  
        
         case 
'K'// d12
         
digitalWrite(12HIGH);
         
d12 1;
         
EEPROM.write(12d12);
         
glavnaia();
         break;
         
         case 
'k'// d12
         
digitalWrite(12LOW);
         
d12 0;
         
EEPROM.write(12d12);
         
glavnaia();
         break;         
      
         case 
'M'// d13
         
digitalWrite(13HIGH);
         
d13 1;
         
EEPROM.write(13d13);
         
glavnaia();
         break;
         
         case 
'm'// d13
         
digitalWrite(13LOW);
         
d13 0;
         
EEPROM.write(13d13);
         
glavnaia();
         break;
 
         default:
         
glavnaia();
       }
     }
   
    else 
// если символ был не 'Y', то очищаем буфер
      
{
        for(
byte i=0255i++) 
         {
           
Serial.read();    
         } 
      } 
     }    
// конец if (Serial.read()=='Y')
   
}    // конец чтение порта
 
// конец loop


void glavnaia() // отправка данных
 
{
      
Serial.print(d2);//0
      
Serial.print(",");
      
Serial.print(d3);//1
      
Serial.print(",");
      
Serial.print(d4);//2
      
Serial.print(",");
      
Serial.print(0);//3  //  пока отключаем, потом пригодится 
      
Serial.print(",");
      
Serial.print(0);//4  //  пока отключаем, потом пригодится 
      
Serial.print(",");
      
Serial.print(0);//5 //  пока отключаем, потом пригодится 
      
Serial.print(",");
      
Serial.print(0);//6 //  пока отключаем, потом пригодится 
      
Serial.print(",");
      
Serial.print(0);//7  //  пока отключаем, потом пригодится 
      
Serial.print(",");
      
Serial.print(0);//8 //  пока отключаем, потом пригодится 
      
Serial.print(",");
      
Serial.print(d11);//9
      
Serial.print(",");
      
Serial.print(d12);//10
      
Serial.print(",");
      
Serial.print(d13);//11 
      
Serial.print(",");
      
Serial.print(shim1); // 12 отсылается 
      
Serial.print(",");
      
Serial.println(shim2); // 13 отсылается 14 значений разделённых запятой
 

Обмен данными с ардуиной описан здесь или тут.

Как работает

Кнопки:

Кнопка (например D13) включит светодиод и запишет в EEPROM единицу. В веб-интерфейс отправится флаг 1 сообщающий о том, что команда выполнена. Кнопка подсветится.

При повторном нажатии, светодиод погаснет и в EEPROM запишется ноль. В веб-интерфейс отправится флаг 0. Кнопка поменяет цвет.

То есть в веб-интерфейсе отобразится только гарантированно выполненная команда.

PHP код:
...
         case 
'M'// d13
         
digitalWrite(13HIGH); // включили
         
d13 1// установили флаг
         
EEPROM.write(13d13); // записали его в память
         
glavnaia(); // функция отправки ответа
         
break;
         
         case 
'm'// d13
         
digitalWrite(13LOW);
         
d13 0;
         
EEPROM.write(13d13);
         
glavnaia();
         break;
... 
Если включить D13 и обесточить ардуину, то при последующем включении ардуина прочитает соответствующую ячейку памяти:

PHP код:
...
byte d13 EEPROM.read(13);
... 
И если там была единица, то в блоке void setup() включит светодиод:

PHP код:
...
  
delay(500);
  if(
d13digitalWrite(13HIGH); else digitalWrite(13LOW); 
Пауза перед включением нужна для того, чтоб НЕ включались все потребители одновременно (например это дача, и ардуиной управляются обогреватели в разных комнатах).


Диммер:

Диапазон значений ШИМ от 0 до 255, ардуина получает (от клиента) значения в диапазоне от 0 до 100, которые внутри программы умножаются на 2.55 и выводятся на «ножку».

PHP код:
         case 'D'// d5 прибавляем shim1
         
shim1++; // прибавили 
         
if(shim1 100shim1 100// если больше ста, то будет сто
         
EEPROM.write(5shim1); // записали значение в память
         
analogWrite(5shim1 2.55); // зажгли лампочку
         
glavnaia(); // функция отправки ответа
         
break;
         
         case 
'd'// d5 убавляем shim1
         
shim1--;
         if(
shim1 1shim1 0;
         
EEPROM.write(5shim1);
         
analogWrite(5shim1 2.55);
         
glavnaia();
         break; 
Если ползунок сдвигается, то в ардуину отсылается команда увеличить/уменьшить ШИМ на единицу (и так далее пока двигаете ползунок). Переменная shim1++; увеличивается, её значение помещается в память, и на пин подаётся shim1 умноженый на 2.55.

После этого значение shim1 отсылается обратно в веб-интерфейс и присваиваются индикатору и ползунку.

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

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

При нажатии на кнопку внутри индикатора:



В ардуину отправится команда обнуляющая значение shim1

PHP код:
         case 'F'// мгновенное включение ШИМ на D5
         
shim1 EEPROM.read(5); // считываем значение ШИМ из EEPROM
         
analogWrite(5shim1 2.55); // включаем ШИМ D5
         
glavnaia();
         break;
         
         case 
'f'// мгновенное отключение ШИМ на D5
         
shim1 0;
         
analogWrite(5shim1); // отключаем ШИМ D5, но НЕ записываем в EEPROM
         
glavnaia();
         break; 
При этом, в память ничего НЕ записывается, а нажатие на соседнюю кнопку вернёт значение из памяти.
(так удобнее отключать свет, нежели ползунок сдвигать)

Интерфейс

Скачайте архив и распакуйте его в рабочую папку сервера (по умолчанию это /var/www), как то так – /var/www/knopki_shimpolz (у вас может быть своя папка).

В браузере зайдите по адресу ваш_роутер/knopki_shimpolz/. Появится вот такая картинка:



Как это работает

Желательно открыть файл index.html из архива, и почитать комментарии.

Диммер:

При первой загрузки страницы, срабатывает функция обновления — show(); (в дальнейшем она работает с установленым интервалом) и у ардуины вместе с другими данными запрашиваются значения ШИМ:

PHP код:
/*обновление*/
show();
setInterval(show,2000);  /* частота обновления в милисекундах */
function show(){  /* функция обновления */
if(flagobnov == 1) { /* это флаг нужен для временного отключения обновления */
            
$.ajax({ 
                
type"GET",
                
url"box2.php?df=o"/* отправка символа о */
                
timeout:200/* время (мс), в течении которого функция будет ждать ответа от сервера */          
                
cachefalse,       
                
success: function(data){   
                                          
                           var 
vars data.split(","); /* разбор строки принятой от ардуино */
                           
if(vars.length == dlina){ /* проверка длины данных (количество блоков разделённых запятой) */
                               
                               /*d2*/
                               
if(vars[0] == 1) { $(".d2otkl").show(); $(".d2vkl").hide(); }  /* в зависимости от принятого флага скрывает/показавыет кнопку вкл или откл */
                               
else if(vars[0] == 0) { $(".d2otkl").hide(); $(".d2vkl").show(); } 

                               
/*d3*/
                               
if(vars[1] == 1) { $(".d3otkl").show(); $(".d3vkl").hide(); }
                               else if(
vars[1] == 0) { $(".d3otkl").hide(); $(".d3vkl").show(); }

                               ...

                               
shim1 vars[12]; /* получаем значение ШИМ */ 
                               
sh1(); /* и выводим его на первый индикатор */ 

                               
shim2 vars[13]; 
                               
sh2();

                               ... 
После получения значения shim1, программа переходит в функцию sh1();

PHP код:
function sh1(){ /* рисование первого индикатора */
  
var $ppc = $('.progress-pie-chart'),
    
percent shim1,
    
deg 360*percent/100;
  if (
percent 50) {
    
$ppc.addClass('gt-50');
  }
  else 
$ppc.removeClass('gt-50');
  $(
'.ppc-progress-fill').css('transform','rotate('deg +'deg)');
  $(
'.ppc-percents span').html(percent+' %       D5  '); /* название на кнопке - D5 */
  
sl1();

Значение shim1 выводится на индикатор (зелёный кружок) и работа передаётся в функцию sl1();

Функция sl1(); устанавливает ползунок в соответствии со значением shim1

PHP код:
function sl1(){ /* первый слайдер */
       
$( "#slider" ).slider({
       
value shim1,
       
min 0,
       
max 100,
       
step 1,
       
slide: function( eventui ) {
       
       ... 
Функция slide: function( event, ui ) ожидает движения ползунка.

Когда ползунок будет сдвинут в ту или иную сторону на одно деление, сработает следующий алгоритм:

Отключается обновление ⇨

PHP код:
flagobnov 0
Проверяется в какую сторону сдвинут ползунок (в большую или меньшую) ⇨

PHP код:
if( ui.value shim1 ){ 
PHP код:
else if( ui.value shim1 ){ 
Ардуине отправляется символ указывающий увеличить (уменьшить) ШИМ на единицу ⇨

PHP код:
$.ajax({  
    
type"GET",  
    
url"box2.php?df=D"/* говорим ардуине что надо увеличить ШИМ  на единицу */ 
Получаем новое значение ШИМ от ардуины и вызывает функцию отрисовки индикатора (sh1();) с новым значением ⇨

PHP код:
shim1 vars[12]; /* получаем от ардуины ответ с новым значением ШИМ */
sh1(); /* и выводим значение ШИМа на индикатор */ 
Включаем обновление ⇨

PHP код:
flagobnov 1
Функция (sh1();) в свою очередь отрисовывает индикатор и передаёт управление в функцию (sl1();).

Функция (sl1();) устанавливает ползунок в соответствии с новым значением ШИМ и ожидает очередного движение ползунка.

Код целиком:

PHP код:
...
unction sh1(){ /* рисование первого индикатора */
  
var $ppc = $('.progress-pie-chart'),
    
percent shim1,
    
deg 360*percent/100;
  if (
percent 50) {
    
$ppc.addClass('gt-50');
  }
  else 
$ppc.removeClass('gt-50');
  $(
'.ppc-progress-fill').css('transform','rotate('deg +'deg)');
  $(
'.ppc-percents span').html(percent+' %       D5  '); /* название на кнопке - D5 */
  
sl1();
}

function 
sl1(){ /* первый слайдер */
       
$( "#slider" ).slider({
       
value shim1,
       
min 0,
       
max 100,
       
step 1,
       
slide: function( eventui ) {  /* отправили новое значение в арду, получили его обратно, отправили на индикатор и отдуда вернули сюда чтоб установить слайдер */
       
flagobnov 0/* пока таскаем ползунок отключаем обновление, чтоб не засорять "эфир" */
           
if( ui.value shim1 ){ /* если потащили ползунок в большую сторону, то увеличиваем ШИМ */
        
$.ajax({  
            
type"GET",  
            
url"box2.php?df=D"/* говорим ардуине что надо увеличить ШИМ  на единицу */
                    
timeout:200,
                    
cachefalse,  
                    
success: function(data){                       
                         var 
vars data.split(",");
                         if(
vars.length == dlina
                             { 
                   
shim1 vars[12]; /* получаем от ардуины ответ с новым значением ШИМ */
                   
sh1(); /* и выводим значение ШИМа на индикатор */
                 
}  
                    }   
             });
           }

           else if( 
ui.value shim1 ){ /* если потащили ползунок в меньшую сторону, то уменьшаем ШИМ */
        
$.ajax({  
            
type"GET",  
            
url"box2.php?df=d"/* говорим ардуине что надо уменьшить ШИМ  на единицу */
                    
timeout:200,
                    
cachefalse,  
                    
success: function(data){                       
                         var 
vars data.split(",");
                         if(
vars.length == dlina
                             { 
                   
shim1 vars[12]; /* получаем от ардуины ответ с новым значением ШИМ */
                   
sh1(); /* и выводим значение ШИМа на индикатор */
                 
}  
                    }   
             });
           }

        
flagobnov 1/* включаем обновление */
       
}
    });
}
... 
Значение индикатора и позиция ползунка, гарантированно соответствуют значению в ардуине.

Нажатие на кнопку «Мгновенное отключение ШИМ» отправляет в ардуину команду обнулить ШИМ, а кнопка «Мгновенное включение ШИМ» запросит у ардуины значение ШИМ, которое было до обнуления.

PHP код:
/* d5 ШИМ */
/*мгновенное включение ШИМ на D5*/
$(".d5shimvkl").click(function(){
                    $.
ajax({  
                     
type"GET",  
                     
url"box2.php?df=F",
                             
timeout:200,
                             
cachefalse,  
                             
success: function(data)
                                {                       
                                  var 
vars data.split(",");
                                    if(
vars.length == dlina
                                       { 
                                          
shim1 vars[12]; /* получаем от ардуины ответ с новым значением ШИМ */
                      
sh1(); /* и выводим значение ШИМа на индикатор */
                                       
}  
                                }   
                        }); 
                     return 
false;
                  
    });

/*мгновенное отключение ШИМ на D5*/
$(".d5shimotkl").click(function(){
                    $.
ajax({  
                     
type"GET",  
                     
url"box2.php?df=f",
                             
timeout:200,
                             
cachefalse,  
                             
success: function(data)
                                {                       
                                  var 
vars data.split(",");
                                    if(
vars.length == dlina
                                       { 
                                          
shim1 vars[12]; /* получаем от ардуины ответ с новым значением ШИМ */
                      
sh1(); /* и выводим значение ШИМа на индикатор */
                                       
}  
                                }   
                        }); 
                     return 
false;
                  
    }); 
Внешний вид

Позиция индикаторов, их цвет и шрифт меняется в файле shim.css

PHP код:
/* первый кружок */
.progress-pie-chart {
  
width200px;
  
height200px;
  
top90px/* позиция */
  
left80px/* позиция */
  
border-radius50%;
  
background-color#E5E5E5;
  
positionabsolute;
}
...
.
ppc-percents span {
  
displayblock;
  
font-size26px/*размер текста на кружках*/
  
font-weight600/*ширина текста на кружках*/
  
font-familyArialHelveticasans-serif/*шрифт*/
  
color#161616; /*цвет текста на кружках*/
  
text-shadow0px 1px 2px #7c7c7c; /*цвет и размер тени текста*/

Размер и позицию ползунков можно менять в файле slai.css

PHP код:
.ui-slider 
positionrelative
width200px/* ширина ползунка */
text-alignleft
outlinenone
}
...
/* кнопка ползунка */
.ui-slider-horizontal .ui-slider-handle 
width50px/*размер кнопки ползунка*/
height50px;
margin-left: -25px
outlinenone;
box-shadow0 0 10px 3px rgba(0,0,0,0.3);
border-radius4px;
border1px solid #2b2c2b;
cursorpointer;
}
...
/*первый ползунок*/
s1 
positionabsolute
top360px
left80px;
font-size26px/*размер текста на кнопках*/
font-weight600/*ширина текста на кнопках*/
font-familyArialHelveticasans-serif/*шрифт*/
color#161616; /*цвет текста на кнопках*/
text-shadow0px 1px 2px #7c7c7c; /*цвет и размер тени текста*/
}

/*второй ползунок*/
s2 
positionabsolute
top360px
left420px;
font-size26px/*размер текста на кнопках*/
font-weight600/*ширина текста на кнопках*/
font-familyArialHelveticasans-serif/*шрифт*/
color#161616; /*цвет текста на кнопках*/
text-shadow0px 1px 2px #7c7c7c; /*цвет и размер тени текста*/

Вот и всё, готово...

Последний раз редактировалось stD; 14.05.2015 в 03:33.
stD вне форума   Ответить с цитированием
 


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Текущее время: 01:53. Часовой пояс GMT +3.


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Яндекс.Метрика