Как выйти из ситуации

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Всем доброго времени суток.
Есть такой вопрос. У меня есть скетч для управления ардуиной с ИК пульта. ВОТ Он:
#include <IRremote.h>

int RECV_PIN = 11; //вход ИК приемника
IRrecv irrecv(RECV_PIN);
decode_results results;
int a=0; // переменная переключения режима, при нажатии кнопки она принимает значение +1
int b=0; //
int c=0; //
int d=0; //
int e=0; //
int f=0; //
int g=0; //
 

void setup()
{
irrecv.enableIRIn(); // включить приемник
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(9, OUTPUT); // назначаем пины как выходы
pinMode(8, OUTPUT);
pinMode(7, OUTPUT);
pinMode(3, OUTPUT);
pinMode(2, OUTPUT);
}

void loop() {
if (irrecv.decode(&results)) {
delay(300); // задержка перед выполнением определения кнопок, чтобы избежать быстрое двойное нажатие

if (results.value == 0xFF807F) {a=a+1;} // обработка нажитя клавиши, здесь переменная принимает значение +1
if (results.value == 0xFFB04F) {b=b+1;}
if (results.value == 0xFF00FF) {c=c+1;}
if (results.value == 0xFF906F) {d=d+1;}
if (results.value == 0xFF20DF) {e=e+1;}
if (results.value == 0xFF10EF) {f=f+1;}
if (results.value == 0xFF30CF) {g=g+1;}

// начинаем включать светодиоды на пинах
if (a==1){digitalWrite(13, HIGH);} else {digitalWrite(13, LOW); a=0;} // действие после нажатия кнопки, если переменная стала равна 1 то
if (b==1){digitalWrite(12, HIGH);} else {digitalWrite(12, LOW); b=0;} // произвести переключение пина в режим HIGH, если же нет то вернуть переменную в исходное состояние
if (c==1){digitalWrite(9, HIGH);} else {digitalWrite(9, LOW); c=0;} // Дествие может быть другим
if (d==1){digitalWrite(8, HIGH);} else {digitalWrite(8, LOW); d=0;} // действие после нажатия кнопки
if (e==1){digitalWrite(7, HIGH);} else {digitalWrite(7, LOW); e=0;} // действие после нажатия кнопки
if (f==1){digitalWrite(3, HIGH);} else {digitalWrite(3, LOW); f=0;} // действие после нажатия кнопки
if (g==1){digitalWrite(2, HIGH);} else {digitalWrite(2, LOW); g=0;} // действие после нажатия кнопки

if (results.value == 0xFFFFFFFF ) //можно убрать
{ //
delay(50); //пауза между повторами //
} //
irrecv.resume(); //

}

}
На данный момент пультом включаются и выключаются светодиоды
Задача состоит в следующем - мне нужно чтобы в этой строчке
"""f (a==1){digitalWrite(13, HIGH);} else {digitalWrite(13, LOW); a=0;}"""
не просто включался светодиод, а чтобы например выполнялась небольшая программка например вот эта :
(void setup и voidloop убрал для сокращения)
int val = 0;  
 
val = analogRead(0); // read the value from
// the sensor
analogWrite(LED, val/4); // turn the LED on at
// the brightness set
// by the sensor
delay(10); // stop the program for
// some time
}
 
Для пущей верности обясню весь процесс работы будущего девайса. Я с пульта включаю\выключаю определенные устройства, одним из которых будет лампа регулируемая ШИМ в зависимости от освещенности.
А вот с программированием я столкнулся впервые, поэтому прошу вашей помощи. 
 
 

Modular
Offline
Зарегистрирован: 05.03.2011

 А в чем проблема выноси (за loop)  в отдельную функцию весь код, который нужно выполнить, и вызывай ее где надо. Тут на сайте было про функции.
void SomeFunction(int LED) {
int val = 0;
val = analogRead(0); 
analogWrite(LED, val/4); 
delay(10); 
}
Вызов:
if (a==1){SomeFunction(13);}

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

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

Modular
Offline
Зарегистрирован: 05.03.2011

 А контроллер какой? Если не Mega, то ШИМ работает, только на портах 3, 5, 6, 9, 10 и 11

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Контроллер MEGA 168A, шим 3,5,6,9,10,11 

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Ну вот сматрите у меня есть устройство на ардуино, оно имеет ИК приемник и я могу управлять выходами с дистанционки. Задействовано около восьми выходов, один из которых работает как ШИМ - это пин3. К пин 3 подключена лампа которая изменяет яркость свечения взависимости от освещения. к другим пинам подключены другие разные устройства которые просто включаются и выключаются.
Лампа изменяет свою яркость управляясь с ардуины, программкой назовем ее "SvetPlav", сэнсор фоторезистор.
ПРоблема в том что не получается у меня впихнуть эту программу в программу ИК управления. Она вообще ведет себя не так как нужно. и стопорит выполнение основной программы ИК управления.
Блин как то так, не знаю как яснее.

Zaliv
Offline
Зарегистрирован: 05.03.2011

 Я думаю было бы проще помощь, если бы ты привел целиком код, который не работает, прямо в том виде как он у тебя не работает. У меня есть подозрение, что у тебя функция на себя "утаскивает" все действие, ну т.е. в цикле начинает, например, fadein - fadeout делать, а arduino в общем случае singlethread.

Цитата:

К пин 3 подключена лампа

Опять же как подключена?

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Вот привел в норм вид код программы:
#include <IRremote.h>

int RECV_PIN = 11; //вход ИК приемника
IRrecv irrecv(RECV_PIN);
decode_results results;
int a=0; // переменная переключения режима, при нажатии кнопки она принимает значение +1
int b=0; //
int c=0; //
int d=0; //
int e=0; //
int f=0; //
int g=0; //
int i=0; //
void setup()
{
irrecv.enableIRIn(); // включить приемник
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(9, OUTPUT); // назначаем пины как выходы
pinMode(8, OUTPUT);
pinMode(7, OUTPUT);
pinMode(3, OUTPUT);
pinMode(2, OUTPUT);
}

void loop() {
if (irrecv.decode(&results)) {

  if (results.value == 0xFF807F) {a++; if (a==1){digitalWrite(13, HIGH);} else {digitalWrite(13, LOW); a=0;}} // если нажата клавиша включаем светодиод, вместо светодиода например лампа через IRLR MOSFET, 
  if (results.value == 0xFFB04F)
 // а вот тут и начинается проблема, и прога толком не выполняется и стопорит выполнение нажатия др. кнопок**************************
{
for (i = 0; i < 255; i++) { // loop from 0 to 254 (fade in)
analogWrite(3, i); // set the LED brightness
delay(10);
}
for (i = 255; i > 0; i--) { // loop from 255 to 1 (fade out)
analogWrite(3, i); // set the LED brightness
delay(10);  
 
 

//******************************************

if (results.value == 0xFF00FF) {c++; if (c==1){digitalWrite(9, HIGH);} else {digitalWrite(9, LOW); c=0;}}
if (results.value == 0xFF906F) {d++; if (d==1){digitalWrite(8, HIGH);} else {digitalWrite(8, LOW); d=0;}}
if (results.value == 0xFF20DF) {e++; if (e==1){digitalWrite(7, HIGH);} else {digitalWrite(7, LOW); e=0;}}
if (results.value == 0xFF30CF) {g++; if (g==1){digitalWrite(2, HIGH);} else {digitalWrite(2, LOW); g=0;}}

irrecv.resume(); //

}


вот таки дела.
Нужно чтобы при нажатии кнопки начал плавно моргать светодиод на ноге 3, но так чтобы в это время другие реагировали на нажатие кнопок.

Modular
Offline
Зарегистрирован: 05.03.2011

 Как Zaliv и сказал, проблема в том, что пока у тебя выболняется fade программы вращается в этих циклах (fade in и fade out), с учетом delay (10) она прогоняет эти два цикла  более 5 секунд,
Я бы тут поступил так - в самых первых строчках объявил две глобальные переменные для fade
int fading = 0; // при нуле  диод не горит, при -1 плавно тухнет, при 1 плавно разгорается
int fadingValue = 0; //от 0 до 255, яркость светодиотда
......................
далее как у тебя
.......................
if (results.value == 0xFFB04F) {fading = 1;} //запускаем
//а ниже будет выполняться выполняться fade, только не сразу весь, а один шаг за весь цикл программы (loop), чтобы не стопорить
//программу и давать другим частям кода считывать значения и т.д. Тут не учтено при каких условиях светодиод будет гаснуть, в
//этом случае, нужно обнулить fade и fadeValue
if (fading ==1) {
   fadeValue++;  
  analogWrite(3, fadeValue); // set the LED brightness
  delay(10);
  if (fadeValue>=255) { //если дошли до 255, то разворачиваемся и гасим 
    fading = -1;
  }
if (fading ==-1) {
   fadeValue--;
  analogWrite(3, fadeValue); // set the LED brightness
  delay(10);
  if (fadeValue<=0) { //если дошли до 0, то разворачиваемся и наращиваем яркость
  fading = 1; //
  }
Код из головы, не компилировал могут быть ошибки, но главное идея

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

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

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Немного уменьшил код:
#include <IRremote.h>
int RECV_PIN = 11; //вход ИК приемника
IRrecv irrecv(RECV_PIN);
decode_results results;
#define LED 7
int ledPin[LED]={2, 3, 7, 8, 9, 12, 13}; // задаем переменную определяющую номера портов
#define PER 7
int a=0;
int b=0;
int c=0;
int d=0;
int e=0;
int f=0;
int g=0;
void setup()
{
irrecv.enableIRIn(); // включить приемник
for (int i=0; i<LED; i++){pinMode(ledPin[i], OUTPUT);}
}
void loop() {
if (irrecv.decode(&results))
{
if (results.value == 0xFF807F) {a++; if (a==1){digitalWrite(ledPin[6], HIGH);} else {digitalWrite(ledPin[6], LOW); a=0;}}
if (results.value == 0xFFB04F) {b++; if (b==1){digitalWrite(ledPin[5], HIGH);} else {digitalWrite(ledPin[5], LOW); b=0;}}
if (results.value == 0xFF00FF) {c++; if (c==1){digitalWrite(ledPin[4], HIGH);} else {digitalWrite(ledPin[4], LOW); c=0;}}
if (results.value == 0xFF906F) {d++; if (d==1){digitalWrite(ledPin[3], HIGH);} else {digitalWrite(ledPin[3], LOW); d=0;}}
if (results.value == 0xFF20DF) {e++; if (e==1){digitalWrite(ledPin[2], HIGH);} else {digitalWrite(ledPin[2], LOW); e=0;}}
if (results.value == 0xFF10EF) {f++; if (f==1){digitalWrite(ledPin[1], HIGH);} else {digitalWrite(ledPin[1], LOW); f=0;}}
if (results.value == 0xFF30CF) {g++; if (g==1){digitalWrite(ledPin[0], HIGH);} else {digitalWrite(ledPin[0], LOW); g=0;}}

irrecv.resume();
}

}
 
 
И понял такую весчь, тут что не делай а библиотека не даст работать моей задумке, каждый раз как проход начинается заного, программа останавливает выполнение в строке  if (irrecv.decode(&results))
и ждет пока не будет нажата какая либо кнопка, так что тут нужно разбираться с библиотекой.

Modular
Offline
Зарегистрирован: 05.03.2011

 Я с этой библиотекой не работал, но я так понимаю идет речь, вот об этой http://www.arcfn.com/2010/11/irremote-library-now-runs-on-teensy.html
С одной стороны в документации написано:
irrecv.decode(&results) - Attempt to receive a IR code. Returns true if a code was received, or false if nothing received yet. When a code is received, information is stored into "results".
Т.е. не должно застревать, она должна возвращать false, если сигнала нет.

С другой в списке поддерживаемых плат только следующие: Teensy, Arduino Mega, and Sanguino.
 

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Ну вот я и говорю что нужно разобраться с библиотекой, все таки подвох то в ней а не в моей проге.
Может и не должно останавливаться, но в процессе "ТЫКА" выяснилось что именно так и происходит. Нажал кнопку программа прошла. Не нажал кнопку она стоит ждет посылки. Это наблюдение я провел просто вставив код блинка вместо определения действия кнопок. Каждый раз как я нажимал кнопку светик моргал, а потом перестовал пока я опять не нажму. 

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

http://www.arduino.ru/Reference/For  ----- Вот сдесь лежит, пример:
 
void loop()
{
int x = 1;
for (int i = 0; i > -1; i = i + x){
analogWrite(PWMpin, i);
if (i = 255) x = -1; // переключение управления на максимуме
delay(10);
}
}
 
Происходит тоже самое, все что вне for () игнорируется. Может всеже это не в библиотеке проблема то а. 
 

Modular
Offline
Зарегистрирован: 05.03.2011

 Кстати, в примере описка. Надо поправить пример, ау модераторы :). 
if (i == 255) x = -1;  правильнее наверное
Nikelbak
Попробуй понавтыкать, Serial.println() с разными цифрами Serial.println(1), Serial.println(2) и т.д. между строками и посмотри точно где оно у тебя зависает. Еще сразу после if (irrecv.decode(&results)) { воткни Serial.Println(results.value) и посмотри, что ты там получаешь

Alexander
Offline
Зарегистрирован: 25.04.2010

Спасибо

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

то есть воткнуть после каждой строки Serial.println(), от 0 до n. Это как работает - можно разяснение. А и еще твердый знак в редакторе у меня не ставится. 
Попробовал вот такой способ организации цикла:
int cikle(){
for (i=0; i<255; i++) { a++; return a;}

а в теле loop(){
b=cikle();
analogWrite(3, b);
digitalWrite(12, HIGH);
delay (50);
digitalwrite(12, LOW)
delay (50);
}
 
Вот тогда все норм, из цикла результат выводится в переменную каждый раз при проходе программы, и таким образом один светодиод моргает а другой плавно зажигается. Но тут теперь остается тока со временем обработки разобраться, или правильнее сказать с delay (); /// Если чето каряво написал поправте, еще не все запомнил.

Modular
Offline
Зарегистрирован: 05.03.2011

 В секции инициализации, втыкаешь вот так
void setup()
{
// Открываем сериный порт
Serial.begin(9600);
}
далее в loop везде, где надо втыкаешь меж строк кода
Serial.println('a');
.................
Serial.println('b');
........................
Serial.println('c');
 
В конце delay(5000); чтобы глазами можно было успеть прочитать, на всякий случай
Открываешь Serial Monitor в программной среде и смотришь, что тебе твоё arduino  возвращает. Debugging такой.

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

ооо прикольно, спосибо большое, попробую. 

Zaliv
Offline
Зарегистрирован: 05.03.2011

Nikelbak пишет:

Попробовал вот такой способ организации цикла:
int cikle(){
for (i=0; i<255; i++) { a++; return a;}

а в теле loop(){
b=cikle();
}

Эм.. у тебя тут в коде что-то не то написано:
int cikle(){
for (i=0; i<255; i++) { a++; return a;}
}
это тоже самое, что и int cikle(){a++;}
i у тебя не будет никогда больше 0, т.к. ты на первой же итерации выходишь из цикла -  return a;
и значение a  у тебя будет бесконечно расти.

Zaliv
Offline
Зарегистрирован: 05.03.2011

 Вставь println, как Modular описал, сам убедись

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

 
int cikle()
{
for (int i=0; i <= 255; i++){
  b=a+1; return b; }

вот прям из программы выдернул, все работает/ ошибся )) писал по памяти 

 

Zaliv
Offline
Зарегистрирован: 05.03.2011

 return b будет завершать цикл, на первом круге, return принудительно выходит из цикла. поставь внутрь
b=a+1;
Serial.println(i);
Serial.println(b);
Serial.println();
return b;
 
и посмотри что он тебе вернет.

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Залил в Arduino и вообще не заработало, даже ни че не написало в serial'е. В эмуляторе работало.
вот переделал, залил работает светодиод плавно зажигается потом тухнет резко и опять плавно зажигается, при вставке
 Serial.println(i); ни чего не пишет:
#define LED 3 // the pin for the LED
int i = 0; // We'll use this to count up and down
int b=0;
int a=0;
void setup() {
pinMode(LED, OUTPUT); // tell Arduino LED is an output
}
void loop(){
b=cikle();
analogWrite(LED, b);
}
int cikle()
{
for (int i=0; i <= 255; i++){
a++;
delay (10);
return a;
}
}
могу скрин выложить.

Alexander
Offline
Зарегистрирован: 25.04.2010

Ну дак правильно, если ты уберешь for и оставишь вот так:
int cikle()
{
a++;
delay (10);
return a;
}
у тебя ничего не изменится. Также это функция будет много раз вызываться из loop наращивая значение переменной a, наращивая яркость светодиода, пока она не перевалит за 255, вот тогда он резко потухнет. Я что пытаюсь сказать - тебе for там не нужен, он у тебя больше одного цикла не делает, он на первом же цикле вываливается из-за return. Return в цикл не ставят, вернее ставят если при каком либо условии хотят прервать цикл.
Чтоб заработало Serial.println надо в Setup добавить Serial.begin(9600);
 

Zaliv
Offline
Зарегистрирован: 05.03.2011

 Хотел тоже самое написать, опередил Alexander. Смотри выше там Modular давал пример как плавное моргание делать

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

 Да действительно, туплю. )))Блин...Огромное спасибо ребят. Прям глаза открываете. А вот с тем что скидывается на 0 я не понял. Т.е. значение для аналогового выхода максимально 255, и если оно переваливает за 255 то автоматом скидывается на 0 так? 

Zaliv
Offline
Зарегистрирован: 05.03.2011

Диапазон значений для analogWrite 0..255, наверно если больше, то просто игнорируется, считается 0, не знаю как там внутри организована борьба с превышением допустимых значений.

Nikelbak
Nikelbak аватар
Offline
Зарегистрирован: 22.03.2011

Т.е. это можно просто принять как факт. 

Modular
Offline
Зарегистрирован: 05.03.2011

 Кстати, для хранения значений в диапазоне 0-255 удобно использовать тип unsigned char, его диапазон значений как раз 0-255. Кстати, в примере выше, скорее всего при его использовании, яркость будет нарастать, потом сбрасываться на 0 при переполнении unsigned char на значении 255 и снова начинать с 0 набирать яркость. Но надо пробовать для верности.