суббота, 22 августа 2015 г.

Управление нагрузками при помощи IR-пульта (ATtiny2313) и приемника(ATtiny13)

Вот такое видео мне скинули на Facebook.


Название наверное на Китайском, так что звучит как-то так:
"Управление нагрузками при помощи IR-пульта (ATtiny2313) и приемника(ATtiny13)".

Схема приёмника(receiver) и передатчика(transmitter) выглядит вот так:


ATtiny13 выступает в роли приёмника, то есть принимает ИК сигнал а ATtiny2313 в роли передатчика, то есть передаёт команды при помощи IR(инфракрасных лучей).

Код для приёмника на базе ATtiny13:

//IR remote control receiver ATtiny13A CPU:8MHz 20130731 1200
#include <avr/io.h>
#include <avr/interrupt.h>
void wait(uint16_t w){
  while(w--){
    volatile uint16_t i=1;
    while(i--);
  }
}

unsigned int c,e; // wait(1)=0.0089ms
char a,b,f,h,k,m1,m2,m3,m4,p;
char s1=0x81,s2=0x41,s3=0xC1,s4=0x21,s5=0xA1,s6=0x61,s7=0xE1,s8=0x11;

//--- PCINT interrupt --------------------------------------------------

ISR(PCINT0_vect){

  c=0;
  while(~PINB & 0x01){
    c++;
    wait(1);
  } // leader check
  if(c>730 && c<950){
    k=1;
  }
  else{
    k=0;
  }

  if(k){
    c=0;
    e=0;
    for(h=0;h<16;h++){ // data
      while( PINB & 0x01){
      }
      while(~PINB & 0x01){
        c++;
        wait(1);
      }
      if(c>160){
        b=1;
      }
      else{
        b=0;
      }
      e=e<<1;
      e|=b;
      c=0;
    }

    if(e==s1*0x100+~s1){
      PORTB|=0b00000010;
      f=1;
    }
    if(e==s2*0x100+~s2){
      PORTB|=0b00000100;
      f=1;
    }
    if(e==s3*0x100+~s3){
      PORTB|=0b00001000;
      f=1;
    }
    if(e==s4*0x100+~s4){
      PORTB|=0b00010000;
      f=1;
    }

    if(e==s5*0x100+~s5 && p==0){
      PORTB^=(1<<PB1);
      p=1;
    }
    if(e==s6*0x100+~s6 && p==0){
      PORTB^=(1<<PB2);
      p=1;
    }
    if(e==s7*0x100+~s7 && p==0){
      PORTB^=(1<<PB3);
      p=1;
    }
    if(e==s8*0x100+~s8 && p==0){
      PORTB^=(1<<PB4);
      p=1;
    }
    a=0;
  }
}
//--- timer interrupt ------------------------------------------------

ISR(TIM0_COMPA_vect){
  a++;
  if(a>10 && f){
    PORTB=0x00;
    a=0;
    f=0;
  }
  if(a>10){
    p=0;
  }
}

//--------------------------------------------------------------------
int main(){

  DDRB  = 0b00011110; // PB0 IR input
  PORTB = 0b00000001;

  GIMSK = 0b00100000; // PCINT enable
  PCMSK = 0b00000001; // PCINT0 mask

  TCCR0A= 0b00000010; // timer0,compare match A,CTC
  TCCR0B= 0b00000100; // clk:256
  TIMSK0= 0b00000100; // compare match A enable
  OCR0A = 255;
  sei();    // interrupt enable

  while(1){

  }
  return 0;
}




Код для передатчика на базе ATtiny2313:

//IR Remote Control Transmitter ATtiny2313 CPU:8MHz 20130731 1500

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#define on  OCR1B=e;
#define off OCR1B=0;
void wait(uint16_t w){
  while(w--){
    volatile uint16_t i=1;
    while(i--);
  }
}

int a=128,e=31,h,k,p; //a=1T a:116-140 個体差があるため要調整

//----- PCINT interrupt ----------------------------------------------

ISR(PCINT_vect){
  if(( PIND & 0x40)&&(~PINB & 0b00000001)){
    k=0x81;
  }
  if(( PIND & 0x40)&&(~PINB & 0b00000010)){
    k=0x41;
  }
  if(( PIND & 0x40)&&(~PINB & 0b00000100)){
    k=0xC1;
  }
  if(( PIND & 0x40)&&(~PINB & 0b00001000)){
    k=0x21;
  }

  if((~PIND & 0x40)&&(~PINB & 0b00000001)){
    k=0xA1;
  }
  if((~PIND & 0x40)&&(~PINB & 0b00000010)){
    k=0x61;
  }
  if((~PIND & 0x40)&&(~PINB & 0b00000100)){
    k=0xE1;
  }
  if((~PIND & 0x40)&&(~PINB & 0b00001000)){
    k=0x11;
  }
  p=1;
  k=k*0x100+~k;
}
//--------------------------------------------------------------------

int main( void ){

  DDRB  = 0b00010000; // PB4 IR output
  PORTB = 0b11101111;
  DDRD  = 0b00000000;
  PORTD = 0b00000000;

  TCCR1A= 0b00100000; // OC1B
  TCCR1B= 0b00010001; // PWM, phase and frequency correct
  ICR1  = 103;  // 38kHz, duty=33%
  off;

  GIMSK= 0b00100000; // PCINT enable
  MCUCR= 0b01010000; // power down mode
  PCMSK =0b00001111; // PCINT3,2,1,0 mask
  sei();    // interrupt enable

  //--------------------------------------------------------------------

  while(1){
    sleep_mode();
    while(p){
      on;
      wait(a*12);  // leader
      for(h=15;h>=0;h--){  // data
        off;
        wait(a);
        on;
        if((k>>h)&1){
          wait(a*3);
        }
        else{
          wait(a);
        }
      }
      off;
      wait(a*50); // a*50にしないと連続受信不可(20130609)
      if((~PINB & 0b00001111)==0){
        k=0;
        p=0;
      }
    }
  }
  return 0;
}





Код и схема взяты из описания под video:

https://youtu.be/Wv_G4hqCgQE

БОЛЬШОЕ спасибо товарищу diorama111:

http://youtube.com/diorama111

Комментариев нет:

Отправить комментарий