Подсветка лестницы

WZV
Offline
Зарегистрирован: 22.09.2012

 Работаю электриком. Начал изучать программирование Arduino. Загорелся написать код, для включения ступенек лестницы. Если нажал на кнопку в низу лестницы, то ступеньки должны загораться по очереди вверх. А если дошел до верха и там нажал на кнопку, то ступеньки должны выключится в такой последовательности с низу на верх. Когда идешь с верху в низ, то ступеньки должны включаться и выключаться сверху в низ. А у меня почему то выключаются со второй кнопки в обратном порядке. Немогу сам додуматься. ПОМОГИТЕ.

int knopka=0;
int knopka2=0;

void setup ()
{
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(12,INPUT);
pinMode(11,INPUT);

}

void loop ()

{


if(digitalRead(12)==LOW&&knopka2==0)//если кнопка нажата
// и перемення "knopka2" равна 0 , то ...
{
delay(50);
knopka2++;//пишем 1 в переменную кнопка
//это нужно для того что бы с каждым нажатием кнопки
//происходило только одно действие

digitalWrite(2, !digitalRead(2));//меняем значение порта на противоположное
delay(1000);
digitalWrite(3, !digitalRead(3));
delay(1000);
digitalWrite(4, !digitalRead(4));
delay(1000);
digitalWrite(5, !digitalRead(5));
delay(1000);
}

if(digitalRead(12)==HIGH&&knopka2==1)//если кнопка НЕ нажата
//и переменная knopka2 равна - 1 ,то ...
{
knopka2=0;//обнуляем переменную "knopka2"
}
if(digitalRead(11)==LOW&&knopka==0)//если кнопка нажата
// и перемення "knopka" равна 0 , то ...
{
delay(50);//защита от дребезга
knopka++;//пишем 1 в переменную кнопка
//это нужно для того что бы с каждым нажатием кнопки
//происходило только одно действие

digitalWrite(5, !digitalRead(5));//меняем значение порта на противоположное
delay(1000);
digitalWrite(4, !digitalRead(4));
delay(1000);
digitalWrite(3, !digitalRead(3));
delay(1000);
digitalWrite(2, !digitalRead(2));
delay(1000);
}

if(digitalRead(11)==HIGH&&knopka==1)//если кнопка НЕ нажата
//и переменная knopka равна - 1 ,то ...
{

knopka=0;//обнуляем переменную "knopka"
}
}
SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Надо с алгоритмом определиться...
Типа :
- кнопка НИЗ ( идём вверх )
- ступенчатое вкл ступеней вверх
- кнопка Верх ( дошёл )
- ступенчатое выкл ступеней вверх
- НЕТ кнопки Верх ( передумал идти )
- гашение подстветки
.
вниз - так же....
.
...надо граф состояний построить, Вы в логике событий чуть запутались....

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Моя - тоже начинающий.... Но - не в логике.....

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Ваша задача - тока без кнопок :)

http://habrahabr.ru/post/142685/

Моя бы пошла по Вашему пути, с кнопками.... На макете....

leshak
Offline
Зарегистрирован: 29.09.2011
  1.  Зачем было плодить темы?
  2. Перед завдением темы стоило ознакомится с прикрепленными ветками на форуме. Что-бы хотя-бы код вставлять по уму.
  3. А уж информативность названия темы - выше всяких похвал. Все сразу догадались о чем идет речь. Темы с просьбой о помощи - они такие редкие. Обычно все заводят темы что-бы найти кому-бы помочь. Да и начинающих тут ну совсем не бывает. Сплошные опытные чаи друг-сдругом пьют. Так что информация про "я начинающий" - самая важная. Именно ее и нужно в название выносить первым делом в название.
maksim
Offline
Зарегистрирован: 12.02.2012

 Оставьте тот же порядок, что и при нажатии на первую кнопку

int knopka=0;
int knopka2=0;

void setup ()
{
  pinMode(2,OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(12,INPUT);
  pinMode(11,INPUT);

}

void loop ()

{

  if(digitalRead(12)==LOW&&knopka2==0)//если кнопка нажата
    // и перемення "knopka2" равна 0 , то ...
  {
    delay(50);
    knopka2++;//пишем 1 в переменную кнопка
    //это нужно для того что бы с каждым нажатием кнопки
    //происходило только одно действие

    digitalWrite(2, !digitalRead(2));//меняем значение порта на противоположное
    delay(1000);
    digitalWrite(3, !digitalRead(3));
    delay(1000);
    digitalWrite(4, !digitalRead(4));
    delay(1000);
    digitalWrite(5, !digitalRead(5));
    delay(1000); 
  }

  if(digitalRead(12)==HIGH&&knopka2==1)//если кнопка НЕ нажата
    //и переменная knopka2 равна - 1 ,то ...
  {
    knopka2=0;//обнуляем переменную "knopka2"
  }
  if(digitalRead(11)==LOW&&knopka==0)//если кнопка нажата
    // и перемення "knopka" равна 0 , то ...
  {
    delay(50);//защита от дребезга
    knopka++;//пишем 1 в переменную кнопка
    //это нужно для того что бы с каждым нажатием кнопки
    //происходило только одно действие

    digitalWrite(2, !digitalRead(2));//меняем значение порта на противоположное
    delay(1000);
    digitalWrite(3, !digitalRead(3));
    delay(1000);
    digitalWrite(4, !digitalRead(4));
    delay(1000);
    digitalWrite(5, !digitalRead(5));
    delay(1000); 
  }

  if(digitalRead(11)==HIGH&&knopka==1)//если кнопка НЕ нажата
    //и переменная knopka равна - 1 ,то ...
  {

    knopka=0;//обнуляем переменную "knopka"
  } 
}

 

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

Код по смыслу идентичный тому который дал Максим.

Только номера светиков оформил массивом (что-бы легче было менять пины и их количество) и убрал дублирование кода выносом переключения состояния светиков в отдельную фукнцию.

#define PAUSE 1000 // длина паузы между сменой состояний диода

int knopka=0;
int knopka2=0;

byte LED_PINS[]={2,3,4,5}; // пины светодиодов, можно менять
#define LED_TOTAL sizeof(LED_PINS)/sizeof(byte) // вычисляем сколько у нас всего светиков


void setup ()
{
    for(byte i=0;i<LED_TOTAL;i++)pinMode(LED_PINS[i],OUTPUT); // включаем светики на выход
  pinMode(12,INPUT);
  pinMode(11,INPUT);

}


void loop ()

{

  if(digitalRead(12)==LOW&&knopka2==0)//если кнопка нажата
    // и перемення "knopka2" равна 0 , то ...
  {
    delay(50);
    knopka2++;//пишем 1 в переменную кнопка
    //это нужно для того что бы с каждым нажатием кнопки
    //происходило только одно действие

     toggle_led_array();
  }

  if(digitalRead(12)==HIGH&&knopka2==1)//если кнопка НЕ нажата
    //и переменная knopka2 равна - 1 ,то ...
  {
    knopka2=0;//обнуляем переменную "knopka2"
  }
  if(digitalRead(11)==LOW&&knopka==0)//если кнопка нажата
    // и перемення "knopka" равна 0 , то ...
  {
    delay(50);//защита от дребезга
    knopka++;//пишем 1 в переменную кнопка
    //это нужно для того что бы с каждым нажатием кнопки
    //происходило только одно действие

     toggle_led_array();
  }

  if(digitalRead(11)==HIGH&&knopka==1)//если кнопка НЕ нажата
    //и переменная knopka равна - 1 ,то ...
  {

    knopka=0;//обнуляем переменную "knopka"
  } 
}

// включает или выключает светодиоды последовательно
void toggle_led_array(){
   for(byte i=0;i<LED_TOTAL;i++){
      digitalWrite(LED_PINS[i],!digitalRead(LED_PINS[i]));
      delay(PAUSE); 
   }
}

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Не каждый новенький - опытный..... Нельзя ли открыть ветку -  " "чЯйники" и их вопросы " ?

WZV - если Ваши ответы поймёт, то "не неопытный" ! Мне трудно понять, что Вы наговорили..... Сразу понять...

....терпение, тока терпение :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Перед регистрацией - или  СРАЗУ после - стОит преподать навыки пользования новичку.....

....а не потом вгонять его в ступор - посмотри там, посмотри сям :(

Это критика была...... :(

....в защиту МАЛЕНЬКИХ !!!!!!

ich
Offline
Зарегистрирован: 10.06.2012

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

#define PAUSE 1000 // длина паузы

uint8_t stupenki[] = {2, 3, 4, 5};
uint8_t stupenki_count = sizeof(stupenki)/sizeof(uint8_t); // Колличество ступенек
uint8_t knopka1 = 11; // Сверху
uint8_t knopka2 = 12; // Внизу
bool knopka1On = false;
bool knopka2On = false;
uint8_t c;

void setup()
{
	for(c=0; c<stupenki_count; c++)
		pinMode(stupenki[c],OUTPUT);
	pinMode(knopka1,INPUT);
	pinMode(knopka2,INPUT);
}
	// С низу в верх
void bottomUp(uint8_t state){
	for(c=(stupenki_count-1); c>=0; c--){
		digitalWrite(stupenki[c], state);
		delay(PAUSE);
	}
}
// С верху в низ
void topDown(uint8_t state){
	for(c=0; c<stupenki_count; c++){
		digitalWrite(stupenki[c], state);
		delay(PAUSE);
	}
}

void loop()
{
	// Верхняя кнопка нажата
	if(digitalRead(knopka1)==HIGH){
		knopka1On = !knopka1On; // Меняем состояние верхней кнопки
		if(knopka2On){ // Выключить в верху нижний выключатель
			bottomUp(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в веху
			if(knopka1On){ // Включено в верху
				topDown(HIGH); // включить с верху в низ
			}else{ // Выключено в верху
				topDown(LOW); // выключить с верху в низ
			}
		}
	}
	// Нижняя кнопка нажата
	if(digitalRead(knopka2)==HIGH){
		knopka2On = !knopka2On; // Меняем состояние нижней кнопки
		if(knopka1On){ // Выключить в низу верхний выключатель
			topDown(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в низу
			if(knopka2On){ // Включено в низу
				bottomUp(HIGH); // включить с верху в низ
			}else{ // Выключено в низу
				bottomUp(LOW); // выключить с верху в низ
			}
		}
	}
}

Вот надеюсь будит работать так как надо. Сам не дуине не проверял, но вот тестовый код на ЯВЕ заработал так как надо.

Тут пример на JAVA

maksim
Offline
Зарегистрирован: 12.02.2012

Есть лесница, предположим, что в данном случае кнопка 1 находится на нижней ступеньке, а кнопка 2 на верхней, когда мы идем на верх, то ступеньки поочередно подсвечиваются снизу в верх и поочередно тухнут тоже с низу в верх. По логике вещей надо бы чтобы когда мы идем в обратном напрравлении (то есть спускаемся по леснице) ступеньки подсвечивались/тухли с верху в низ.
Этот алгоритм реализован в коде ich'а, я подредактировал вариант leshak'а, получилось как-то так:

#define PAUSE 1000 // длина паузы между сменой состояний диода

boolean knopka=0;
boolean knopka2=0;
boolean dir = 0;

byte LED_PINS[]={
  2,3,4,5}; // пины светодиодов, можно менять
#define LED_TOTAL sizeof(LED_PINS)/sizeof(byte) // вычисляем сколько у нас всего светиков


void setup (){
  for(byte i=0;i<LED_TOTAL;i++)pinMode(LED_PINS[i],OUTPUT); 
}


void loop ()
{
  if(!digitalRead(12) && !knopka2){//если кнопка нажата
    knopka2=1;//пишем 1 в переменную кнопка 
    if(LED_PINS[LED_TOTAL-1]){
      dir = 0;
    }
    else{
      dir = 1;
    }
    toggle_led_array(dir);
  }

  if(digitalRead(12) && knopka2){//если кнопка НЕ нажата
    knopka2=0;//обнуляем переменную "knopka2"
  }

  if(!digitalRead(11) && !knopka){//если кнопка нажата
    knopka=1;//пишем 1 в переменную кнопка
    if(LED_PINS[0]){
      dir = 1;
    }
    else{
      dir = 0;
    }
    toggle_led_array(dir);
  }

  if(digitalRead(11) && knopka){//если кнопка НЕ нажата
    knopka=0;//обнуляем переменную "knopka"
  } 
}


// включает или выключает светодиоды последовательно
void toggle_led_array(boolean dir){
  if(dir){
    for(byte i=LED_TOTAL-1;i>=0;i--){
      digitalWrite(LED_PINS[i],!digitalRead(LED_PINS[i]));
      delay(PAUSE); 
    }
  }
  else{
    for(byte i=0;i<LED_TOTAL;i++){
      digitalWrite(LED_PINS[i],!digitalRead(LED_PINS[i]));
      delay(PAUSE); 
    }
  }
}

 

ich
Offline
Зарегистрирован: 10.06.2012
delay(50);//защита от дребезга

На сколько чисто освобождает этот кусочик, кнопку от дребезга?

Я как-то пытался на лабе освободить кнопку от дребезга с помощью кондёров и резисторов, нифига не вышло. Пришлось мутить с NOT-IC и т.д.

maksim
Offline
Зарегистрирован: 12.02.2012

 Я обычно ставлю 150 - 200, этого в полне достаточно для устранения дребезга при нажатии пальцем, а точнее это минимальное время между нажатиями, которые можно сделать пальцем. Дребезга при этом не замечал. Странно что не получилось избавиться от дребезга кондерами...
В данном случае нет смысла избавляться от дребезга при нажатии, так как после первого же срабатывания кнопки начнется цикл подсветки, а он длится долго. Но есть смысл поставить задержку для устранения дребезга при отпускании кнопки... но это только в том случае если кнопка еще не отпущена, а цикл подсветки уже закончился.

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

SU-27-16 пишет:

....а не потом вгонять его в ступор - посмотри там, посмотри сям :(

Ветки прикрепленные - есть. Только их же никто не читает. Заходят на форум, не пытаются, для начала посмотреть "что уже есть" - сразу заводить свою. Даже если такая же тема уже есть тремя строками ниже.

Если бы их читали - половина "посмотри там, посмотри сям" - небыло-бы. А втроая половина эта - банальный здравый смысл и уважение к другим. Его в FAQ никак не напишешь.  Что нужно написать в faq? Перед постом прочитайте глазами другого человека? Задумайтесь соотвествует ли тема тому что вы дальше будете писать? Имеет ли она хоть какой-то смысл? Дайте ссылки/схемы на то что вы используете? Если не предполагать в новичках здравый смысл, то FAQ будет на 5-ть страниц. И его, опять-таки, никто читать не будет. Повесить большими буквами "пишите со смыслом"? 

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

ich пишет:

delay(50);//защита от дребезга

На сколько чисто освобождает этот кусочик, кнопку от дребезга?

Смотря что вы подразумеваете под "чисто". Если "от ложных сработок" - то да. довольно нормально (особенно если, как сказал Максим, число чутьб ольше сделать".

Смотрите что у вас происходит.

При нажатии кнопки ( предположим она 0 - не нажата, 1 - нажата) вот такая картина на ней.

0,0,0, (начинаем-нажимать), 1,0,0,1,0,1,1,0,1 , (дожалось плотно, дребезг прекратился), 1,1,1,1,1,1, (отпустили), 0,1,1,0,1,0,0 (полностью отжалась) ,0,0,0,0,0,0

Вот такая картину у нас без "анти дребезга". Как видим у нас, хотя мы нажали один раз имеется куча "нажатий отпусканий". Спасает то что они "очень кратковременны". Теперь. Если мы, после первой же 1 вставили delay(), то контроллер просто перестает на что-либо реагировать (пока delay() работает). И если он "проснулся" к тому времени когда кнопка уже пришла в состояние "полностью отжалась" - все "дребезги", он "проспал".

Вообщем мы как бы "выкинули" из его жизни то кусок времени когда происходит дребезг.

Если же вы имеете ввиду под "чисто" - какие-то побочные эффекты, то... да. delay() - крайне нежелательная функция в реальных скетчках. Он останавливает скетч. В этот момент ничего не происходит. Например если в этот момент будет нажата другая кнопка - мы провороним это (или какой-то счетчик импульсов у нас, или степеер в этот момент хотим крутить и т.п.). У нас нет "многозадачности". А delay() - все забрал на себя.

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

Запоминаем, где-то в конце loop, предыдущие состояние кнопки. В начале loop, читаем кнопки сравниваем "предыдущие и текущие" состояние. И выясняем поменялось оно или нет (и куда, нажали или отжали). Этим макаром мы избавляемся от многократных сработок типа "нажали кнопку и держат". Далее когда мы заметили что состояние "изменилось" - мы с помощью millis() - запоминаем когда изменилось. И теперь, кроме проверки того-что изменилось, проверяем еще "а сколько прошло времени с прошлого изменения". Если меньше какой-то порога - игнорируем (значит это дребезг). 

Или, вместо "запомнили когда было изменения", просто делаем опрос кнопок не при каждом проходе loop, а раз, к примеру в 200 msec. Тогда, опять-таки, все "мелкие дребезги" мы проморгаем.

unsigned long lastButtonScan=0;

void loop(){
  if(millis()-lastButtonScan>200){ // с прошлого опроса кнопок прошло 200 msec
      ..... опрашиваем кнопки .....
      lastButtonScan=millis();// запомнили когда мы опросили кнопки
  } 
}

Но, естественно, при таких подходих и при зажигании/гашении диодов желательно отказатся от использования delay().

Кстати побочным эффектом этого, станет возможно завести "аварийную кнопку". Типа диоды пошли зажигатся, а мы передумали и нажали "стоп". С deley() - это не возможно. Пока он выполняется "мы глухи и слепы".

WZV
Offline
Зарегистрирован: 22.09.2012

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

ich
Offline
Зарегистрирован: 10.06.2012

leshak пишет:

Смотря что вы подразумеваете под "чисто". Если "от ложных сработок" - то да. довольно нормально (особенно если, как сказал Максим, число чутьб ольше сделать".

...

Если же вы имеете ввиду под "чисто" - какие-то побочные эффекты, то... да. delay() - крайне нежелательная функция в реальных скетчках. Он останавливает скетч.

Спасибо, как всегда на высоте и доступно. Класс

Под "чисто" конечно я имел в виду всётаки второй вариант. Так как знаю что delay() замараживает всю работу программы.

Я бы конечно пытался бы лучше решать пробоему дребезга не с программной стороны а с железячной. Но как я уже пЫсал, кондёров и резисторов не достаточно. Или у меня руки золотые и ростут из золотой ...ы ;-). Хотя нет, я ведь на Лабе не один был, по этому шанс корявых рук тендирует к нулю.

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

ich пишет:

Я бы конечно пытался бы лучше решать пробоему дребезга не с программной стороны а с железячной. Но как я уже пЫсал, кондёров и резисторов не достаточно. Или у меня руки золотые и ростут из золотой ...ы ;-). Хотя нет, я ведь на Лабе не один был, по этому шанс корявых рук тендирует к нулю.

А я не вижу чем тут железное лучше (кроме экономии памяти). Фактически вы делаете обсолютно тоже самое - импульсы меньше какой-то длины "сжираете" конденсатором. Делаете их не существующими для контроллера. Но... становитесь зависимы от точности самих деталей. У них же тоже параметры гуляют. Как он производителя, так и от температуры, качества дорожек и т.п. Плюс, на конденсаторе если "шумящие ипульсы" идут слишком часто он может "переполнится" и не отфильтровать все помехи. Это как на машине. Одинокую яму - амортизатор отработает. А вот если у вас 300 метров стиральной доски - в итоге удары уже пойдут на корпус. Он не будет испевать "разжиматся". "Програмный" - не имеет памяти. Ему что 10, что 100 импульсов по 5-ть мсек - без разницы. Главное что все они "меньше порога".

Аппаратный - так легко не подстроишь. 50 мсек, на 200 мсек - легкиим движением не поменяешь. Да и вообще четко "вот ровно 200 порог" - не сделаете. Поменялась температура - поменились харрактеристики вашей RC-цепочки и т.п. Решили на другом вольтаже работать - опять переделывай... .  Аккум подсел - поплыли временные характеристики...

Вообщем, возможно во мне говорит программер :) Мне всегда програмное нравится больше. Так как оно более подконтрольно и детерменировано. По крайней мере для меня.

P.S. Плюс чем больше делателей тем дороже, больше размер, меньше надежность (больше возможных точек отказа).

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

WZV пишет:

Прошу не судить меня строго, 

Мне вот интерестно, почему все новички ждут что тут будут кого-то судить? Ардуино - платформа любителей (не потому что "она слаба", а маркетинг так ее спозиционировал).  А если и будуn, то вам-то что? Ваша жизнь поменяется от мнения незнакомых вам людей? :)

Негатив и тыкание носом, обычно, происходят не от малых "програмерских знаний", а на уровне межчеловеческого общения. Когда человек "не читает ответы", не дает достаточно инфы о своей проблеме, ленится сам приложить усилия, хочет что-бы ему на блюде все подали....и т.п.

По поводу возраста - поверте освоить рояль намного сложней :) И не накручивайте сами себя по поводу "это сложно". Да и все.

Хотя, конечно, возможно, будет немного сложновато перестроить мышления с "аналогового", на "дискретный". Вы, как электрик, скорее всего привыкли что у вас все происходит "одновременно", а тут не так. Когда пишите програму, пытайтесь себя представить контролером, а программу "пошаговым рецептом". Причем за раз может выполнятся только один шаг. Приучайтесь смотреть на программу и пытатся выполнить ее в голове вместо контроллера. Вообразить "что при этом происходит". На каждой строчке.

Можете, для облегчение понимания логики програмы, взять бумажку. Нарисовать на ней овалы в которых подписаны состояния вашего контроллера, типа "диоды выключены", "зажигаем_диоды" (процесс), "диоды включены", между ними стрелочки указывающе из какого состояния в какой можно переходить. Над стрелочками подписать при каких условиях может происходть этот переход. Например из "диоды выключены" в "диоды включены" переходим при "нажата кнопка 1".

Такая бумажка и вам может помочь разложить "по полочкам", и, если эту картинку на форуме опубликуете, другим понять "что же выхотите". Быстрее найти различие между "что нужно" и "как это реализовано в коде".

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

Переименовал тему в более отражающую "суть". А то меня каждый раз "типает", от взгляда на главную страницу с такой темой:) Надеюсь не будете возражать.

WZV
Offline
Зарегистрирован: 22.09.2012

 Поправил только здесь: if(digitalRead(knopka1) == LOW) и if(digitalRead(knopka2) == LOW)

Заработало хорошо в варианте верняя кнопка нажата. Вариант, нижняя кнопка нажата, спупени включаются в нужном порядке, после этого кнопки на сигнал не реагируют, Arduino зависает нужно делать reset. Долго искал причину, но ума не хватило.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Выложите крайнюю версию скетча, пожста.

WZV
Offline
Зарегистрирован: 22.09.2012

 Извиняюсь не написал что использовал код ich

WZV
Offline
Зарегистрирован: 22.09.2012

код ich

 

#define PAUSE 1000 // длина паузы

uint8_t stupenki[] = {2, 3, 4, 5};
uint8_t stupenki_count = sizeof(stupenki)/sizeof(uint8_t); // Колличество ступенек
uint8_t knopka1 = 11; // Сверху
uint8_t knopka2 = 12; // Внизу
bool knopka1On = false;
bool knopka2On = false;
uint8_t c;

void setup()
{
	for(c=0; c<stupenki_count; c++)
		pinMode(stupenki[c],OUTPUT);
	pinMode(knopka1,INPUT);
	pinMode(knopka2,INPUT);
}
	// С низу в верх
void bottomUp(uint8_t state){
	for(c=(stupenki_count-1); c>=0; c--){
		digitalWrite(stupenki[c], state);
		delay(PAUSE);
	}
}
// С верху в низ
void topDown(uint8_t state){
	for(c=0; c<stupenki_count; c++){
		digitalWrite(stupenki[c], state);
		delay(PAUSE);
	}
}

void loop()
{
	// Верхняя кнопка нажата
	if(digitalRead(knopka1) == LOW){
		knopka1On = !knopka1On; // Меняем состояние верхней кнопки
		if(knopka2On){ // Выключить в верху нижний выключатель
			bottomUp(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в веху
			if(knopka1On){ // Включено в верху
				topDown(HIGH); // включить с верху в низ
			}else{ // Выключено в верху
				topDown(LOW); // выключить с верху в низ
			}
		}
	}
	// Нижняя кнопка нажата
	if(digitalRead(knopka2) == LOW){
		knopka2On = !knopka2On; // Меняем состояние нижней кнопки
		if(knopka1On){ // Выключить в низу верхний выключатель
			topDown(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в низу
			if(knopka2On){ // Включено в низу
				bottomUp(HIGH); // включить с верху в низ
			}else{ // Выключено в низу
				bottomUp(LOW); // выключить с верху в низ
			}
		}
	}
}

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Лучше весь снова, с Вашими исправлениями..... Хочется тоже изучить, как пишут опытные....

ich
Offline
Зарегистрирован: 10.06.2012

WZV пишет:

 Поправил только здесь: if(digitalRead(knopka1) == LOW) и if(digitalRead(knopka2) == LOW)

Интересно, а какая у вас логика в кноках? При нажатии на кнопку вы садите её на "LOW-минус" а при отпущенной на "HIGH-плюс"? 

WZV пишет:

Arduino зависает нужно делать reset. Долго искал причину, но ума не хватило.

...

Извиняюсь не написал что использовал код ich

Я на ардуине не пробывал, но явавский-алгоритм работал как надо. Завтро если будет время гляну ещё разок.

maksim
Offline
Зарегистрирован: 12.02.2012

ich пишет:

Интересно, а какая у вас логика в кноках? При нажатии на кнопку вы садите её на "LOW-минус" а при отпущенной на "HIGH-плюс"? 

А чему вы так удевляетесь?
1. У ATMega нет PULL-DOWN, но есть PULL-UP резисторы, поэтому более логично использовать именно такую логику, дабы не паять лишние подтягивающие резисторы.
2. Это мугут быть и не кнопки, а какие-нибудь датчики, у которых сигнальный вывод при срабатывании "опускается" к GND, я бы даже сказал, что большенство цифровых датчиков именно так и работает.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 А так ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Тестовый вариант :

#define Pause 2000
#define Stage4 11               // --------- светодиод
#define Stage3 10               // --------- светодиод
#define Stage2 9                // --------- светодиод
#define Stage1 8                // --------- светодиод
#define BtnUp 3                 // --------- кнопка
#define BtnDown 2               // --------- кнопка   
volatile byte Direct = 0 ;      // 1 - идём вверх, 2 - идём вниз
//-----------------------------------------------------------------------
void setup()
{
  Serial.begin( 9600 ) ;
  pinMode( Stage4 , OUTPUT ) ;
  pinMode( Stage3 , OUTPUT ) ;
  pinMode( Stage2 , OUTPUT ) ;
  pinMode( Stage1 , OUTPUT ) ;
  pinMode( BtnUp , INPUT ) ;
  digitalWrite( BtnUp , HIGH ) ;     // подтяжка к + 
  pinMode( BtnUp , INPUT ) ;
  digitalWrite( BtnDown , HIGH ) ;   // подтяжка к +  
  attachInterrupt( 0, GetUpIR , FALLING ) ;
  attachInterrupt( 1, GetDownIR , FALLING ) ;
  DDRB = B0000 ;
}
//-----------------------------------------------------------------------
 void GetUpIR()
{  
  Direct = 1 ;
}
//-----------------------------------------------------------------------
 void GetDownIR()
{  
  Direct = 2 ;
}
//-----------------------------------------------------------------------
 void GetUp()
{  
  Serial.println( DDRB , BIN ) ;
  DDRB = B0001 ;
  Serial.println( DDRB , BIN ) ;
  for ( byte n = 0 ; n < 3 ; n ++ )
  {
    delay( Pause ) ;
    DDRB = DDRB << 1 ;
    Serial.println( DDRB , BIN ) ;
  }
  delay( Pause ) ;
  DDRB = B0000 ;
  Direct = 0 ;
  Serial.println( DDRB , BIN ) ;
  Serial.println( "" ) ;
}
//-----------------------------------------------------------------------
 void GetDown()
{  
  Serial.println( DDRB , BIN ) ;
  DDRB = B1000 ;
  Serial.println( DDRB , BIN ) ;
  for ( byte n = 0 ; n < 3 ; n ++ )
  {
    delay( Pause ) ;
    DDRB = DDRB >> 1 ;
    Serial.println( DDRB , BIN ) ;
  }
  delay( Pause ) ;
  DDRB = B0000 ;
  Direct = 0 ;
  Serial.println( DDRB , BIN ) ;
  Serial.println( "" ) ;
}
//------------------------------------------------------------------------
 void loop()
{  
  if ( Direct == 1 )
  {
    GetUp() ;
  }
    if ( Direct == 2 )
  {
    GetDown() ;
  }
}
//------------------------------------------------------------------------

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Боевой :

#define Pause 1000
#define Stage4 11               // --------- светодиод
#define Stage3 10               // --------- светодиод
#define Stage2 9                // --------- светодиод
#define Stage1 8                // --------- светодиод
#define BtnUp 3                 // --------- кнопка
#define BtnDown 2               // --------- кнопка   
volatile byte Direct = 0 ;      // 1 - идём вверх, 2 - идём вниз
//-----------------------------------------------------------------------
void setup()
{
  pinMode( Stage4 , OUTPUT ) ;
  pinMode( Stage3 , OUTPUT ) ;
  pinMode( Stage2 , OUTPUT ) ;
  pinMode( Stage1 , OUTPUT ) ;
  pinMode( BtnUp , INPUT ) ;
  digitalWrite( BtnUp , HIGH ) ;     // подтяжка к + 
  pinMode( BtnUp , INPUT ) ;
  digitalWrite( BtnDown , HIGH ) ;   // подтяжка к +  
  attachInterrupt( 0, GetUpIR , FALLING ) ;
  attachInterrupt( 1, GetDownIR , FALLING ) ;
  DDRB = B0000 ;
}
//-----------------------------------------------------------------------
 void GetUpIR()
{  
  Direct = 1 ;
}
//-----------------------------------------------------------------------
 void GetDownIR()
{  
  Direct = 2 ;
}
//-----------------------------------------------------------------------
 void GetUp()
{  
  DDRB = B0001 ;
  for ( byte n = 0 ; n < 3 ; n ++ )
  {
    delay( Pause ) ;
    DDRB = DDRB << 1 ;
  }
  delay( Pause ) ;
  DDRB = B0000 ;
  Direct = 0 ;
}
//-----------------------------------------------------------------------
 void GetDown()
{  
  DDRB = B1000 ;
  for ( byte n = 0 ; n < 3 ; n ++ )
  {
    delay( Pause ) ;
    DDRB = DDRB >> 1 ;
  }
  delay( Pause ) ;
  DDRB = B0000 ;
  Direct = 0 ;
}
//------------------------------------------------------------------------
 void loop()
{  
  if ( Direct == 1 )
  {
    GetUp() ;
  }
    if ( Direct == 2 )
  {
    GetDown() ;
  }
}
//------------------------------------------------------------------------

 

ich
Offline
Зарегистрирован: 10.06.2012

 

void loop()
{
	// Верхняя кнопка нажата
	if(digitalRead(knopka1)==LOW){
		digitalWrite(13, HIGH); // Зажигаем Инфо-LED
		knopka1On = !knopka1On; // Меняем состояние верхней кнопки
		if(knopka2On){ // Выключить в верху нижний выключатель
			bottomUp(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в веху
			if(knopka1On){ // Включено в верху
				topDown(HIGH); // включить с верху в низ
			}else{ // Выключено в верху
				topDown(LOW); // выключить с верху в низ
			}
		}
		digitalWrite(13, LOW); // Тушим Инфо-LED
	}
	// Нижняя кнопка нажата
	if(digitalRead(knopka2)==LOW){
		digitalWrite(13, HIGH); // Зажигаем Инфо-LED
		knopka2On = !knopka2On; // Меняем состояние нижней кнопки
		if(knopka1On){ // Выключить в низу верхний выключатель
			topDown(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в низу
			if(knopka2On){ // Включено в низу
				bottomUp(HIGH); // включить с верху в низ
			}else{ // Выключено в низу
				bottomUp(LOW); // выключить с верху в низ
			}
		}
		digitalWrite(13, LOW); // Тушим Инфо-LED
	}
}

Попробуйте помаргать LED на 13 Пине для чтобы точно знать что Дуина повисла, а не ушла в неизвестное состояние. В верхнем коде я добавил маргание Info-LED. Нажимаете кнопку лампочка загарелась, алгоритм прокрутился лампочка потухла. Таким оброзом можно отследить нажатие кнопок и за одно понять висит дуина или нет.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Заодно и вопрос :

Прерывания 0 и 1 имеют приоритеты между собой ?

Пока тестил по 2 секунды на ступенку заметил, что пока выполняется ВВЕРХ - нет реакции на прерывание 1.

И пока выполняется ВНИЗ - нет реакции на прерывание 0.

Расскажите, пожста, в описаниях - не нашёл.....

maksim
Offline
Зарегистрирован: 12.02.2012

SU-27-16 пишет:

Заодно и вопрос :
Прерывания 0 и 1 имеют приоритеты между собой ?

Да имеют - 0 приоритней 1.
SU-27-16 пишет:

Пока тестил по 2 секунды на ступенку заметил, что пока выполняется ВВЕРХ - нет реакции на прерывание 1.
И пока выполняется ВНИЗ - нет реакции на прерывание 0.
Расскажите, пожста, в описаниях - не нашёл.....

Прерывания срабатывают, но в тот момент, когда идет цикл подсветки никак не влияют на ход программы.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Только я логику поменял....

Нажали внизу - вкл_1 - секунда - выкл_1 и вкл_2 - секунда - выкл_2 и вкл_3 - секунда - выкл_3 и вкл_4 - секунда - выкл_4 .

Нажали вверху - бегущая ступенька вниз.

Ваша задумка :

Нажали внизу - вкл_1 - секунда - вкл_1 и вкл_2 - секунда - вкл_1 и вкл_2 и вкл_3 - секунда - вкл_1 и вкл_2 и вкл_3 и вкл_4 .

Светятся 4 ступени.

 

Передумали подниматься - нажали внизу - подсветка всех ступеней выкл.

 

Всё-таки взобрались и нажали вверху - выкл_1 - секунда - выкл_2 - секунда - выкл_3 - секунда - выкл_4 .

 

Сверху вниз - идентично.

 

Вы так задумали ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Когда выполняется void GetUp() или void GetDown() - нет реакции на прерывания !!!!!!

В этот момент уже мы вышли же из прерывающих void GetUpIR() или void GetDownIR()......

И в чём приоритет 0 перед 1 ? Если выполняется прерывающая_1 и пришло прерывание_0 - будет выход из прерывающей_1 и запустится прерывающая_0 ?

ich
Offline
Зарегистрирован: 10.06.2012

maksim пишет:

А чему вы так удевляетесь?
1. У ATMega нет PULL-DOWN, но есть PULL-UP резисторы, поэтому более логично использовать именно такую логику, дабы не паять лишние подтягивающие резисторы.
2. Это мугут быть и не кнопки, а какие-нибудь датчики, у которых сигнальный вывод при срабатывании "опускается" к GND, я бы даже сказал, что большенство цифровых датчиков именно так и работает.

И действительно, Вы правы. Прсто я пока начинаю осваивать апарат, навыка ещё нету чтобы сразу очевидне в глаза бросилось. Я бы к Вашему примеру поткрепил бы ещё вот эту ссылку . Так как для новичков не сразу понятно что происходит в Вашем примере. Мне прешлось по "Гогэлить" чтобы понять что Вы придумали. ;-)

maksim
Offline
Зарегистрирован: 12.02.2012

 Это не мой пример.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

 Ага... Я цитирует Максима, а ответил мне....

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

WZV
Offline
Зарегистрирован: 22.09.2012

ich пишет:

 

void loop()
{
	// Верхняя кнопка нажата
	if(digitalRead(knopka1)==LOW){
		digitalWrite(13, HIGH); // Зажигаем Инфо-LED
		knopka1On = !knopka1On; // Меняем состояние верхней кнопки
		if(knopka2On){ // Выключить в верху нижний выключатель
			bottomUp(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в веху
			if(knopka1On){ // Включено в верху
				topDown(HIGH); // включить с верху в низ
			}else{ // Выключено в верху
				topDown(LOW); // выключить с верху в низ
			}
		}
		digitalWrite(13, LOW); // Тушим Инфо-LED
	}
	// Нижняя кнопка нажата
	if(digitalRead(knopka2)==LOW){
		digitalWrite(13, HIGH); // Зажигаем Инфо-LED
		knopka2On = !knopka2On; // Меняем состояние нижней кнопки
		if(knopka1On){ // Выключить в низу верхний выключатель
			topDown(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в низу
			if(knopka2On){ // Включено в низу
				bottomUp(HIGH); // включить с верху в низ
			}else{ // Выключено в низу
				bottomUp(LOW); // выключить с верху в низ
			}
		}
		digitalWrite(13, LOW); // Тушим Инфо-LED
	}
}

Попробуйте помаргать LED на 13 Пине для чтобы точно знать что Дуина повисла, а не ушла в неизвестное состояние. В верхнем коде я добавил маргание Info-LED. Нажимаете кнопку лампочка загарелась, алгоритм прокрутился лампочка потухла. Таким оброзом можно отследить нажатие кнопок и за одно понять висит дуина или нет.

В варианте "Верхняя кнопка нажата"  LED на 13 Пине в начале алгоритма включается, в конце алгоритма выключается. А в варианте "Нижняя кнопка нажата" LED на 13 Пине в начале алгоритма включается, включаются ступени и все так зависает, кнопки не реагируют.

maksim
Offline
Зарегистрирован: 12.02.2012

 Попробуйте так:

#define PAUSE 1000 // длина паузы

uint8_t stupenki[] = {2, 3, 4, 5};
int stupenki_count = sizeof(stupenki)/sizeof(uint8_t); // Колличество ступенек
uint8_t knopka1 = 11; // Сверху
uint8_t knopka2 = 12; // Внизу
bool knopka1On = false;
bool knopka2On = false;

void setup()
{
	for(int c = 0; c<stupenki_count; c++)
		pinMode(stupenki[c],OUTPUT);
	pinMode(knopka1,INPUT);
	pinMode(knopka2,INPUT);
}
	// С низу в верх
void bottomUp(uint8_t state){
	for(int c = stupenki_count-1; c>=0; c--){
		digitalWrite(stupenki[c], state);
		delay(PAUSE);
	}
}
// С верху в низ
void topDown(uint8_t state){
	for(int c = 0; c<stupenki_count; c++){
		digitalWrite(stupenki[c], state);
		delay(PAUSE);
	}
}

void loop()
{
	// Верхняя кнопка нажата
	if(digitalRead(knopka1) == LOW){
		knopka1On = !knopka1On; // Меняем состояние верхней кнопки
		if(knopka2On){ // Выключить в верху нижний выключатель
			bottomUp(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в веху
			if(knopka1On){ // Включено в верху
				topDown(HIGH); // включить с верху в низ
			}else{ // Выключено в верху
				topDown(LOW); // выключить с верху в низ
			}
		}
	}
	// Нижняя кнопка нажата
	if(digitalRead(knopka2) == LOW){
		knopka2On = !knopka2On; // Меняем состояние нижней кнопки
		if(knopka1On){ // Выключить в низу верхний выключатель
			topDown(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в низу
			if(knopka2On){ // Включено в низу
				bottomUp(HIGH); // включить с верху в низ
			}else{ // Выключено в низу
				bottomUp(LOW); // выключить с верху в низ
			}
		}
	}
}

 

WZV
Offline
Зарегистрирован: 22.09.2012

 Ура! Заработало maksim

WZV
Offline
Зарегистрирован: 22.09.2012

 Я очень благодарен ВСЕМ за помощь!!!

ich
Offline
Зарегистрирован: 10.06.2012

maksim пишет:

 Попробуйте так:

#define PAUSE 1000 // длина паузы

uint8_t stupenki[] = {2, 3, 4, 5};
int stupenki_count = sizeof(stupenki)/sizeof(uint8_t); // Колличество ступенек
uint8_t knopka1 = 11; // Сверху
uint8_t knopka2 = 12; // Внизу
bool knopka1On = false;
bool knopka2On = false;

void setup()
{
	for(int c = 0; c<stupenki_count; c++)
		pinMode(stupenki[c],OUTPUT);
	pinMode(knopka1,INPUT);
	pinMode(knopka2,INPUT);
}
	// С низу в верх
void bottomUp(uint8_t state){
	for(int c = stupenki_count-1; c>=0; c--){
		digitalWrite(stupenki[c], state);
		delay(PAUSE);
	}
}
// С верху в низ
void topDown(uint8_t state){
	for(int c = 0; c<stupenki_count; c++){
		digitalWrite(stupenki[c], state);
		delay(PAUSE);
	}
}

void loop()
{
	// Верхняя кнопка нажата
	if(digitalRead(knopka1) == LOW){
		knopka1On = !knopka1On; // Меняем состояние верхней кнопки
		if(knopka2On){ // Выключить в верху нижний выключатель
			bottomUp(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в веху
			if(knopka1On){ // Включено в верху
				topDown(HIGH); // включить с верху в низ
			}else{ // Выключено в верху
				topDown(LOW); // выключить с верху в низ
			}
		}
	}
	// Нижняя кнопка нажата
	if(digitalRead(knopka2) == LOW){
		knopka2On = !knopka2On; // Меняем состояние нижней кнопки
		if(knopka1On){ // Выключить в низу верхний выключатель
			topDown(LOW); // выключить с верху в низ
			knopka1On = false; // Выключить верхнюю кнопку
			knopka2On = false; // Выключить нижнюю кнопку
		}else{ // Включить/выключить в низу
			if(knopka2On){ // Включено в низу
				bottomUp(HIGH); // включить с верху в низ
			}else{ // Выключено в низу
				bottomUp(LOW); // выключить с верху в низ
			}
		}
	}
}

 

Пожалуйста, пожалуйста, пожалуйста. Объясните мне что это за фокус? Я не думал что у uint8_t с цифрами от 0 до 4 поблемы. Или это гон из за глобальной перименной с, если да то мне это тоже интерессно почему.

maksim
Offline
Зарегистрирован: 12.02.2012

 Я особо не вникал в этот вопрос, но когда тип byte с, по какой то причине с-- глючит. Что там происходит я не знаю, ну и на всякий случай сделал с не глобальной....

maksim
Offline
Зарегистрирован: 12.02.2012

 А все понял. Смотрите:

  byte i = 10;
  while(i >= 0){
    i--;
  }

что бы условие i >= 0 стало не верным i должна стать меньше нуля, а так как i не может быть отрицательной, то условие всегда будет верным и цикл получается вечный.
Поэтому надо объявлять тип char или int8_t.

ich
Offline
Зарегистрирован: 10.06.2012

Ну точно. Блин вот я дал, где глаза то были.

Спасибо за проведённую экспертизу! ;-)

Тогда можно так:

uint8_t i = 10;
do{
	i--;
	// Что-нибудь делать
}while(i>0);