В детскую часы на 2812 8х8 и пульт

Функцию чтения сигналов с ИК датчика. Хотелось бы чтоб она возвращала код кнопки типа код=irread(); Но так можно пробовать если отказаться от прерываний.

:slight_smile:
Как же она может, если чётко написано:
…функция, вызываемая прерыванием, функция должна быть без параметров и не возвращать значений. В англоязычной документации употребляется термин interrupt service routine для такой функции.

Кому возвращала? Вы же её сами не вызываете. У Вас всё в голове смешалось. Покажите где и как Вы её вызываете, тогда я покажу как она может возвращать.

Ничего не понятно, но очень интересно™
Быстрое - в прерываниях, хотя бы в таймерных, но достаточно частых.

В детской IMHO часы должны быть стрелочные. Дети ещё не понимают время по цифрам, не ощущают его. А вот по стрелкам маленькая большая чисто зрительной памятью ощущают когда надо вставать, кушать, гулять, спать. Это подобно эффекту стрелочного спидометра, когда шофёр психологически, взглядом в моменте, оценивает скорость авто. Когда цифры, уходит в разы больше времени на преобразование мозгом цифр в скорость. Когда то давно была защищена целая диссертация на тему стрелочных приборов расположенных на стене электростанций. Их там больше сотни иногда установлено. Так вот дежурный, проводя взглядом справа на лево всю доску, мог оценить всё ли нормально с оборудованием на станции. А именно создаётся некий стробоскопический стрелочный эффект - плавная волна. И если возникает где то неисправность, то эта волна прерывается, и надо конкретно выявлять прибор показыающий сбой в системе. Сейчас это может уже не актуально с приходом автоматики и разного рода сигнализаций с выставлением пороговых значений, но лет 20-30 назад такое было, что помогало быстро реагировать на обстановку и устранять возникшие неисправности. По этому до сих пор милисикунды в автомобильной промышленности ловят стрелками, хоть они и стали электронными во многих щитках авто.

1 лайк

ТС придумал часы, в них функция безбиблиотечная чтения ИК приёмника. Она мне стала интересна, её подправил, теперь она работает и с делеями в скетче. Вот его (как я понял) первопредставление скетча:

Я твёрдо стою на ногах.
…во так вот хочется :slight_smile:

// для ИК пульта приёмник без библиотеки
#define plus 4 //
#define minus 3 //
#define IK_PIN 2 //



void setup() {
//  
pinMode(IK_PIN, INPUT);  // ir recv
pinMode(plus,OUTPUT);//
digitalWrite(plus,HIGH);// плюс питания ик приёмника
pinMode(minus,OUTPUT);//
digitalWrite(minus,LOW);// минус питания ик приёмника
// 
attachInterrupt(0, irread, FALLING);
Serial.begin(9600);
}
void loop() {
if(irread()!=0){Serial.println(irread(), HEX);// печатаем код кнопки 
  //код по обработке значений irread()
}
delay(100);
}
/////////////////////////////////////////
word irread() {
volatile static byte n = 0;
volatile static word keycode = 0;
volatile static unsigned long tm = 0;
volatile static unsigned long last = 0;

  tm = micros() - last;
  last = micros();
  n += 1;
  if (tm > 3000) {
    keycode = 0;
    n = 0;
    }
  if (n >8&&n<=32) {
    if (tm > 1500) {keycode += 1;}
    keycode = keycode << 1;
  }
  if(n==32){return keycode;keycode = 0; n = 0;}
  else {return 0;}
}
//////////////////////////////////////////

Картинка стрелкоположений.

Писал уже… У нас кадр в 11 классе на ЕГЭ потребовал цифровые часы - стрелочные потому как не понимал :slight_smile:

Нынче среди молодежи это повальное явление

Ну, да, как герои Высоцкого:

А теперь включите мозги.

Функция написана для того, чтобы быть вызванной когда на пине 2 происходит переход с HIGH на LOW. И она уверена, что раз её вызвали, значит такой переход произошёл. На этой уверенности и основана вся её логика.

Вы же “хотите” вызывать её просто так, в любое время, не обращая внимания на пин 2. Просто вызывать, когда Вашей левой пятке приспичит. И что? Будет она при этом работать? Сами-то подумайте.

Вот об этом я и не подумал :frowning:

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

я признаю только стрелочные, там видно типа “10 минут до трех”. А вот дите говорит, что стрелочные не воспринимает сходу, цифры ему привычнее. Дитё правда большое совсем…

О, а я думал открою всем на это глаза ))

А без прерываний? Есть же функция pulseIn().
…Хотя это чисто познавательный вопрос, а с практической точки зрения уже приделал к управлению огнём.
VID_20220816_172322

Все правильно. Поэтому и должно быть:

Иначе стрелочные никогда не освоят.

// для ИК пульта
byte n = 0;
word keycode = 0;
unsigned long tm = 0;
unsigned long last = 0;
void setup() {
  pinMode(2, INPUT);  
  attachInterrupt(0, irread, FALLING);
  Serial.begin(9600);
}

void irread() {  // ловим и считаем пачку импульсов
  tm = micros() - last;
  last = micros();
  n += 1;
  if (tm > 3000) {
    keycode = 0;
    n = 0;
  }
  if (n > 8) {
    if (tm > 1500) keycode += 1;
    keycode = keycode << 1;
  }
}

word key() {
  if (n == 32) {
    n = 0;
    return keycode;
  } else return 0;
}

void loop() {

  Serial.println(key(), HEX);
}

функция key()

надо в конце трех процедур добавить ch=’ ';
set_hhmm();
ch_clr();
fact_pres();

из настройки времени попадаешь в настройку цвета, если минута =2
и сотрешь все цвета, если установил время где минута = 3

word k=key();
if (k>0) Serial.println(k, HEX);

а то одни нули с редким кодом кнопки

Не знаю, я пробую дальше на ёлке, с volatile - как надо :slight_smile:
Вот такой вариант из 96 пикселей с приёмником на пинах 234 и лентой на 6 пине. Работает со сбоями - либо не реагирует на нажатие, либо код с ошибкой в значении кода с кнопки. Но в целом работает хорошо, ибо проверено с дивана :slight_smile:
Для программиста конечно мой код сложноват в понимании.

Спойлер
/////////////////////////////////////
/// примеры для ws2812b
////////////////////////////////////
#define plus 4 //
#define minus 3 //
int IK_PIN = 2;        //Пин подключения выходного сигнала с ИК-приёмника
       


#include "Adafruit_NeoPixel.h"
#define line_ 96 //число пикселей в ленте
uint8_t dataPin = 6;// вывод для подключения
Adafruit_NeoPixel strip = Adafruit_NeoPixel(line_,dataPin , NEO_BRG + NEO_KHZ800);// Создаем переменную strip для управления нашей лентой.

volatile word keycode_ = 0;// переменная хранения кода кнопки

byte R=0; byte G=0; byte B=0;//составляющие цвета пикселя
int t=50;// пауза между кадрами
int effekt=1;// номер эффекта
int M=10;//коэффициент мощности свечения пикселя 
long Y=0;//переменная хранения моментов времени
byte cvet=0;//
long Y1=0;//переменная хранения моментов времени
int ti = 0;
int ni = 0;
 
///RGB
void setup() {
pinMode(plus,OUTPUT);//
digitalWrite(plus,HIGH);// плюс питания ик приёмника
pinMode(minus,OUTPUT);//
digitalWrite(minus,LOW);// минус питания ик приёмника  
pinMode(IK_PIN, INPUT);  // ir recv
attachInterrupt(0, irread, FALLING);
 strip.begin();
Serial.begin(9600); 

}
void loop() {
 
 ///
 /*
 //автоматический перебор программ каждые 2 минуты
 if(millis()-Y>120000ul){
 Y=millis();
 t=25*random(1,4);//псевдослучайный выбор длительности паузы между кадрами в эффекте
 effekt--; if(effekt==0){effekt=19;}//
 M=random(3,11);//псевдослучайный выбор яркости свечения
 cvet=random(0,4);//псевдослучайный выбор компонент цвета 
 }
 */
 /// 
 // проигрывание программы эффекта
   for ( ti = 0; ti < line_; ti++) {//перебор номеров кадров в ленте
    for ( ni = 0; ni < line_; ni++) {//перебор номеров пикселей в ленте
     cvet_(ti,ni);// функция определения цвета пикселя в зависимости от его номера в ленте и момента времени (кадра анимации)   
     if(cvet==0){strip.setPixelColor(ni, R*M, G*M, B*M);}if(cvet==1){strip.setPixelColor(ni, G*M, B*M, R*M);}if(cvet==2){strip.setPixelColor(ni, B*M, R*M, G*M);}if(cvet==3){strip.setPixelColor(ni, R*M, B*M, G*M);}
    
    }
   strip.show(); keypressed(); 
  // delay_(t);
     delay(t);
  }
 ///
 }
///////////////////////////////////////
void cvet_ (int it,int in){
 
 switch (effekt) {
    
    case 1:
     if(in==it){R=0;G=14;B=2;}else{R=7;G=1;B=0;}//бегущий по оранжевой ленте -> цвета бирюзового пиксель ->
      break;
    case 2:
     { byte mnogo=9; R=5*((in+it%mnogo)%mnogo);G=5*((mnogo-1-(in+it%mnogo)%mnogo));B=0;}// бегущая по ленте <-палитра от зелёного до красного (переход из 9 штук)<-
      break;
    case 3:
      if(in<=it){R=5;G=0;B=10;}else{R=0;G=10;B=0;}// ->полоса фиолетового цвета набегает на полосу зелёного ->
      break;
     case 4:
      if(in%(it+1)==0){R=15;G=15;B=10;}else{R=7;G=1;B=1;}// -> выстрел белыми пикселями с их взаиморазлётом -> на розовом фоне 
      break;
      case 5:
        if(in==line_-it||in+1==line_-it||in+2==line_-it||in+3==line_-it||in+4==line_-it){R=15;G=3;B=0;}else{R=0;G=0;B=7;}//бегущий по синей ленте -> цвета оранжевого 5 пикселей ->
      break;
    case 6:
     { byte mnogo=10; R=5*((in+it%mnogo)%mnogo);G=0;B=5*((mnogo-1-(in+it%mnogo)%mnogo));}// бегущая по ленте <-палитра от синего до красного (переход из 10 штук)<-
      break;
    case 7:
      if(in<=line_-it){R=10;G=10;B=0;}else{R=0;G=7;B=7;}// <-полоса голубого цвета набегает на полосу жёлтого <-
      break;
     case 8:
      if(in%(it+1)==0){R=15;G=15;B=10;}else{R=0;G=2;B=2;}// -> выстрел белыми пикселями с их взаиморазлётом -> на голубом фоне 
      break;
    case 9:
     { byte mnogo=32; R=3;G=1*(mnogo-1-(it%mnogo));B=1*((it%mnogo));t=200;}// плавный переход цвета ленты от "зеленоватого к синеватому"
      break;  
    case 10:
     { byte mnogo=32; R=1*(mnogo-1-(it%mnogo));G=1;B=1*((it%mnogo));t=200;}// плавный переход цвета ленты от "красноватого к синеватому"
      break; 
    case 11:
     { byte mnogo=7; R=0*((mnogo-1-(in+it%mnogo)%mnogo));G=2*((mnogo-1-(in+it%mnogo)%mnogo));B=5*((mnogo-1-(in+it%mnogo)%mnogo));}// бегущая по ленте <-поток метеоров (переход из 7 штук)<-
      break; 
     case 12:
     {if(in==it){R=0;G=1;B=0;}if(in+1==it){R=10;G=0;B=0;}if(in+2==it){R=10;G=3;B=0;}if(in+3==it){R=10;G=10;B=0;}if(in+4==it){R=0;G=10;B=0;}
     if(in+5==it){R=0;G=10;B=10;}if(in+6==it){R=0;G=0;B=15;}if(in+7==it){R=3;G=0;B=10;} }// бегущая по ленте ->радуга (переход из 7 штук)->
      break;
     case 13:  
     {if(in<=line_-it){R=0;G=1;B=0;}if(in+2==line_-it){R=10;G=0;B=0;}if(in+4==line_-it){R=10;G=3;B=0;}if(in+6==line_-it){R=10;G=10;B=0;}if(in+8==line_-it){R=0;G=10;B=0;}
     if(in+10==line_-it){R=0;G=10;B=10;}if(in+12==line_-it){R=0;G=0;B=15;}if(in+14==line_-it){R=3;G=0;B=10;} }// бегущая по ленте <-радуга (переход из 7 штук через 1)<-
      break; 
      case 14:  
    {if(in-2<(line_+2*it)/2&&in+2>(line_-2*it)/2&&it<line_/2){R=0;G=7;B=7;}else{if((in>it||in<line_-it)&&it>=line_/2){R=0;G=7;B=7;}else{R=5;G=1;B=5;}} }//<-разбегание от центра поочерёдное полосы синеватого и сиреневого цветов - подобие волны->
      break; 
   case 15:  
    {if(in-2<(line_+2*it)/2&&in+2>(line_-2*it)/2&&it<line_/2){R=0;G=7;B=1;}else{if((in>it||in<line_-it)&&it>=line_/2){R=0;G=7;B=1;}else{R=15;G=2;B=0;}} }//<-разбегание от центра поочерёдное полосы зеленоватого и оранжевого цветов - подобие волны->
      break; 
     case 16:  
    { if((in>=it-3&&in<=it+3)||(in>=it-3+8&&in<=it+3+8)){R=0;G=0;B=0;}else{ R=2*(it%2);G=2*((it%4)/2);B=2*((it%8)/4);} t=70;}//-> бег тень 6 пикселей, светящиеся 1 пиксель, тень 6 пикселей -> на фоновом радужном переливе 
      break;
       case 17:
     R=random(0,(in+it)%7+2); G=random(0,in%10+2); B=random(0,it%10+2);t=140;// рандом пикселей 
      break; 
       case 18:
     {R=(in/16+it)%2;G=((in/16+it)/2)%2;B=((in/16+it)/4)%2;M=40;if(R==0&&G==0&&B==0){R=7;G=1;B=0;M=5;}t=140;}//радужное движение групп по 16 пикселей с добавкой оранжевого
      break; 
       case 19:
     {R=((it+in)/(5))%2;G=(((it+in)/(5))/2)%2;B=(((it+in)/(5))/4)%2;M=40;if(R==0&&G==0&&B==0){R=7;G=1;B=0;M=5;}t=70;}//радужное движение групп по 16 пикселей с добавкой оранжевого 2 вариант
      break;                            
     default:
      { R=0;G=0;B=0;}//выключаем пиксели если не выбран эффект
  } 
}
/////////////////////////////////////////
void irread() {
volatile static byte n = 0;
volatile static word keycode = 0;
volatile static unsigned long tm = 0;
volatile static unsigned long last = 0;

  tm = micros() - last; 
  last = micros();
  n += 1;
  if (tm > 3000) {
    keycode = 0;
    n = 0;
    }
  if (n >8&&n<=32) {
    if (tm > 1500) {keycode += 1;}
    keycode = keycode << 1;
  }
  if(n==32){keycode_ = keycode;keycode = 0;n=0;}
}
//////////////////////////////////////////
void keypressed() {
 if(keycode_!=0){
  Serial.println(keycode_, HEX);// печатаем код кнопки 
  //код по обработке значений keycode_
   switch (keycode_) {
    case 0x906E:
    effekt++;//выбор - номер эффекта
    if(effekt>19){effekt=1;}
      break;
    case 0x51AE:
    effekt--;//выбор - номер эффекта
    if(effekt<1){effekt=19;}
      break;
   case 0x50AE:
     M=M+2;if(M>10){M=10;}//выбор яркости свечения 
      break;
    case 0xD12E:
      M=M-2;if(M<0){M=1;}//выбор яркости свечения
      break; 
      case 0xC03E:
      cvet++;if(cvet>3){cvet=0;}//выбор компонент цвета  
      break; 
       case 0xA15E:
       t=t+70;if(t>210){t=70;}//выбор длительности паузы между кадрами в эффекте 
      break;
      default:
      ti=ni=line_;      
    }
  keycode_ = 0;
   }  
 }
//////////////////////////////////////////////
/////////////////////////////////////////////////
// функция временной задержки с проверкой поступающих данных
void delay_(int T1)
{
Y1=millis();  
while(millis()-Y1<T1){
 
// keypressed();
    
}
}
////////////////////////////////////////////////
 

 
 
 

1 лайк