ик не принимается если померить напряжение ацп

std
Offline
Зарегистрирован: 05.01.2012
#include <LiquidCrystal.h>
#include <IRremote.h>

IRrecv irrecv(9);
LiquidCrystal lcd(11, 10, 5, 4, 3, 2);

decode_results results;
unsigned long last_ir,last_bat;
int i_bat;
float f_bat;
char s_bat[6];

void setup(){
  irrecv.enableIRIn();
  last_ir=millis();
  last_bat=millis();
  lcd.begin(16,2);
  lcd.clear();
  lcd.cursor();
  lcd.blink();
  lcd.setCursor(0,0);
  lcd.print("LCDM init Ok.");
  delay(1500);
}

void loop() {
  if(irrecv.decode(&results) && millis()-last_ir>250){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Protocol: ");
    switch (results.decode_type) {
      case -1:
        lcd.println("RAW   ");
        break;
      case 1:
        lcd.println("NEC   ");
        break;
      case 2:
        lcd.println("SIRC  ");
        break;
      case 3:
        lcd.println("RC5   ");
        break;
      case 4:
        lcd.println("RC6   ");
        break;
    }
    lcd.setCursor(0,1);
    if(results.bits!=0){
      lcd.print("Length: ");
      lcd.print(results.bits, HEX);
    }else{
      lcd.print("Read error");
    }
    delay(1500);
    if(results.bits!=0){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Data:");
      lcd.setCursor(0,1);
      lcd.print(results.value, HEX);
      delay(2000);
    }
    irrecv.resume();
    last_ir=millis();
  }else{
    if(millis()-last_bat>500){
      i_bat=analogRead(A0);
      if(i_bat<100){
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("No Bat");
        lcd.setCursor(0,1);
        lcd.print("No IR data");
      }else{
        f_bat=i_bat/176.283;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Voltage: ");
        dtostrf(f_bat,1,4,s_bat);
        lcd.print(s_bat);
        lcd.setCursor(0,1);
        lcd.print("Charge: ");
        f_bat/=5.4;
        f_bat*=100;
        dtostrf(f_bat,3,2,s_bat);
        lcd.print(s_bat);
        lcd.setCursor(15,0);
        lcd.print(" ");
        lcd.setCursor(13,1);
        lcd.print("%");
        irrecv.enableIRIn();
      }
      irrecv.resume();
      last_bat=millis();
    }
  }
}

показывает либо данные ик кода, если посветить из пульта, либо напряжение и заряд, если подключить к A0 батарею из 4х NiMH через делитель 1k+5.1k. суть проблемы: после того как в первый раз подключу батарею - все, коды больше не ловятся вплоть до ресета, как ты там не свети в ЦОП, хоть пульт в трех сантиметрах от него.

где туплю?

step962
Offline
Зарегистрирован: 23.05.2011

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

Опять же - для повышения читабельности и удобства в отладке - вынесите более-менее длинные (от десяти строк и выше) неветвящиеся куски кода в отдельные функции.

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

PS: еще неплохо было бы придерживаться общепринятых стандартов в написании С-кода: лично я спотыкаюсь об конструкцию

}else{

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

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

 Попробуйте разделить мухи и котлеты IR/LCD и батарейки.

Возмьмите пример IRrecvDump.pde (он поставляется вместе с библиотекой IRremote) и посмотрите в Serial, что там у вас приходит. Рабоатет ли у вас вообще IR нормально.

Кстати, обратите внимание, что у вас  irrecv.resume(); вызывается далеко не после каждого irrecv.decode, да и delay-и вы используете, что тоже может способствовать потери импульсов и IR-a.

 

std
Offline
Зарегистрирован: 05.01.2012

поправил, надеюсь так понятно:

#include <LiquidCrystal.h>
#include <IRremote.h>

IRrecv irrecv(9);
LiquidCrystal lcd(11, 10, 5, 4, 3, 2);

decode_results results;   // буфер TSOP'а
unsigned long last_ir,    // когда последний раз ловили код,
              last_bat;   // мерили напряжение аккума
int i_bat;                // целое 0..1023 с напряжением
float f_bat;              // с точкой
char s_bat[6];            // вывод на LCD

void setup(){
  irrecv.enableIRIn();    // заводим TSOP
  last_ir=millis();
  last_bat=millis();
  lcd.begin(16,2);        // заводим LCD
  lcd.clear();
  lcd.cursor();
  lcd.blink();
  lcd.setCursor(0,0);
  lcd.print("LCDM init Ok.");
  delay(1500);
}

void loop() {                    // мотаем цикл
  if(irrecv.decode(&results) && millis()-last_ir>250){
                       // поймали что-то цопом и с прошлого
                       // раза прошло больше 1/4 сек
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Protocol: ");     // пытаемся понять что за код
    switch(results.decode_type){   
      case -1:
        lcd.println("RAW   ");
        break;
      case 1:
        lcd.println("NEC   ");
        break;
      case 2:
        lcd.println("SIRC  ");
        break;
      case 3:
        lcd.println("RC5   ");
        break;
      case 4:
        lcd.println("RC6   ");
        break;
    }
    lcd.setCursor(0,1);
    if(results.bits!=0){         // код непустой, показываем длину
      lcd.print("Length: ");
      lcd.print(results.bits, HEX);
    }else{                       // ошибка чтения
      lcd.print("Read error");   
    }
    delay(1500);                 // ждем после того как показали
                                 // протокол и длину
    if(results.bits!=0){         // код был непустым, показываем
      lcd.clear();               // сам код
      lcd.setCursor(0,0);
      lcd.print("Data:");
      lcd.setCursor(0,1);
      lcd.print(results.value, HEX);
      delay(2000);               // показали код, ждем
    }
    irrecv.resume();             // продолжаем TSOP
    last_ir=millis();            // запомнили метку времени, когда
                                 // в последний раз TSOP словил код
  }else{                         // это делаем если кода не было
    if(millis()-last_bat>500){   // прошло больше 0.5 сек
      i_bat=analogRead(A0);      // читаем ацп
      if(i_bat<100){             // если меньше 0.5 В то считаем
        lcd.clear();             // что это помехи и не показываем
        lcd.setCursor(0,0);
        lcd.print("No Bat");
        lcd.setCursor(0,1);
        lcd.print("No IR data");
      }else{                     // напряжение больше 0.5 В, показываем
        f_bat=i_bat/176.283;     // компенсируем ацп и делитель, т. е
                                 // из ацп будет 0..1023, а там еще был
                                 // делитель на ~1.2
                                 // получаем 0..6
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Voltage: ");  // конвертируем напряг в массив char
        dtostrf(f_bat,1,4,s_bat);    // и показываем
        lcd.print(s_bat);
        lcd.setCursor(0,1);
        lcd.print("Charge: ");
        f_bat/=5.4;              // считаем процент от аккума
        f_bat*=100;
        dtostrf(f_bat,3,2,s_bat);// конвертируем и показываем
        lcd.print(s_bat);
        lcd.setCursor(15,0);
        lcd.print(" ");
        lcd.setCursor(13,1);
        lcd.print("%");
        irrecv.enableIRIn();     // это уже я дописал в надежде что сбросит
                                 // залипший ЦОП, не помогло, можно убрать
      }
      irrecv.resume();           // еще одна припарка мертвому, можно убрать
      last_bat=millis();         // запомнили метку времени, когда
                                 // в последний раз мерили напряжение
    }                            // конец условия про ограничение в 0.5 сек
  }                              // конец второй части условия про код, т. е.
                                 // в том случае если код не словили,
                                 // ломились прочитать и показать напряг,
                                 // либо если там меньше полвольта, говорили
                                 // что нету батарейки и не было кодов
}                                // конец дежурного цикла

 

std
Offline
Зарегистрирован: 05.01.2012

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

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

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

Я вижу что автор библиотеки всегда вызывает  irrecv.resume(); после удачного irrecv.decode(), а вы - нет. Я вижу что у автора библиотеки irrecv.decode(), вызывается как можно чаще - у вас нет. 

Спорить и доказывать - не буду. Возможно и ошибаюсь. Считаете что это не влияет - OK. Ищите другую причину. Принимать советы во внимание или нет - ваше дело.

step962
Offline
Зарегистрирован: 23.05.2011

std пишет:
суть проблемы: после того как в первый раз подключу батарею - все, коды больше не ловятся вплоть до ресета, как ты там не свети в ЦОП, хоть пульт в трех сантиметрах от него.

А что происходит после того, как в первый раз подключите батарейку?

Ветка измерения напряжения продолжает выполняться? По каким признакам это видно?

Вообще - что-нибудь меняется в системе после рокового подключения?

М.б. вы благополучно подвисаете?

Я бы на вашем месте вывод millis на дисплей дополнительно впиндюрил, ну или мигалку на 13-й ноге задействовал, чтобы видеть, что программа по крайней мере крутится.

Ну а отладочный вывод в Serial в каждой ветви вашего логического лабиринта - это вообще мечта...

Чтобы слишком много в порт не писалось - опять-таки на время отладки - можно в основном цикле delay вставить секунд эдак на две или даже пять (гулять так гулять). При этом, конечно, и диапазоны времени, участвующие в проверках, можно соответствующим образом изменить.

И кстати - определить их константами. Ибо негоже по телу программы цифири разбрасывать - с течением времени умучаетесь их изменять/настраивать. А если еще два числовых значения с разным логическим смыслом совпадут, то потенциальный геморрой на подходе.

std
Offline
Зарегистрирован: 05.01.2012

leshak пишет:
irrecv.resume(); после удачного irrecv.decode(), а вы - нет

где же нет, строка 68.

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

как можно чаще вставить decode() если честно - ну просто некуда, в лупе слушаем цоп, поймали, вызвали resume(), дальше делаем с results че хотим, бо decode() уже вызвалось в условии. все.

возможно опять какие-то накладки с таймерами, как в моем прошлом вопросе. исходник IRrecvDump читал, в сериал посылал. там прием такой же, только без запрета по времени. кстати там resume() делается в песледнюю очередь.

step962

точно известно что не виснет. если отцепить аккум - покажет No bat, No IR data.

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

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

 >где же нет, строка 68.

все-таки хочется поспорить? А сама строчка 68-мь, разве всегда у вас вызывается после irrecv.decode(&results)? Вот это услови " millis()-last_ir>250" всегда гарантированно истинно? Тогда нафига оно вообще?

Так что "поймали, вызвали resume()" у вас выполняется далеко не всегда.

 

std
Offline
Зарегистрирован: 05.01.2012

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

step962
Offline
Зарегистрирован: 23.05.2011

Ну, если не знаете, что еще придумать - переткните свой монитор напряжения на А1,А2 и т.д.

Вход TSOP тоже по ножкам подвигайте - может и найдете устойчивую комбинацию

std
Offline
Зарегистрирован: 05.01.2012

all, проблема на atmega168 никак не вылечилась, в мк atmega328 все стало работать нормально. код скетча никак не менялся, просто зашил в 328.

step962
Offline
Зарегистрирован: 23.05.2011

 ну, поскольку камни в линейке ATMegaX8 в основном отличаются  размером flash/RAM, то проблема, скорее всего, была связана с тем,что вы не вмещались в пределы 1 КБ RAM (ATMega168). При 2 КБ RAM (ATMega328) появилось свободное место, управляющие структуры перестали портиться, логика стала отрабатываться, как ей и положено...