There was a need to turn off the old, but quite working speaker system from the TV remote, without getting up from the sofa. Thinking, I decided to use the IR receiver, which was once unscrewed from the old TV. IR receiver turned out to be unmarked. Having determined the outputs using the spear method, I found out that he is from the TSOP4xxx series, according to the picture:
Googling and having trained on the Arduino UNO, using this code and making sure that the sensor is working, I switched to rewriting the code on ATtiny13. Turning to it, I realized that it is very limited resources, both in flash and in RAM. At first, it was difficult to optimize for the size of the firmware, the controller still did not work, and when I realized that the memory used in the code is much more than 64 bytes, I had to specifically take up the optimization. As a result, with a grief in half, I optimized the code and assembled a prototype on a breadboard. Glad as a child! It blinked as I need. ')
General form:
Mockup
Scheme:
Spoiler
The time has come to translate the entire breadboard into textolite. The board was manufactured by the LUT method. The first pancake, as they say, lumpy. Having made the first scheme, having printed and assembled, I realized that nothing works. I incorrectly connected the LM317T. Besides, having broken Pyataks and tearing off some too thin tracks, I decided to make a second board. I made 0.7mm tracks in it and, having increased the pennies, somehow coped with a part of the problems. Here, too, it was not without problems, because again LM317T was connected incorrectly, and in the previous version of the board the receiver was also burned by submitting 12V to it.
By the way, this case is powered by 12V (I had a low-power transformer, so I used it). The choice of voltage was also due to the available 12V relay. To reduce the voltage for the microcontroller to 5V, the LM317T stabilizer is used, and the KP819 transistor at hand is used to control the relay.
SprintLayout final fee:
Spoiler
Used parts:
ATtiny13A microcontroller;
Resistors 470, 1300, 2x330 and 90 Ohm;
KT819 transistor;
LM317T stabilizer;
2 LEDs red and green;
TSOP4XXX Series Receiver or compatible;
The capacitor is approximately 200-220µF;
Diode 1N4001 or equivalent.
As for the code.
The original version was very weighty and could not work on ATtiny13 either. It was necessary to get rid of a heavy two-dimensional array. The code was very strange: “low” pulses were also recorded, but they were not used at all. In general, I threw out a two-dimensional array and this freed up at least 64 bytes of RAM. I calculated signals on the fly, but this was not enough and after adding the timer functionality, I had to cut variables as much as possible.
Code for Arduino IDE
#define IRpin_PIN PINB #define IRpin 2 #define rLedPin 3 #define gLedPin 4 #define relayPin 1 #define MAXPULSE 5000 #define NUMPULSES 32 #define RESOLUTION 2 #define timeN1 1800000 #define timeN2 3600000 #define timerInterval 500 bool relayState = false; unsigned long timer = 0; unsigned long shift = timeN1;//30min timer by default unsigned long previousMillis = 0; bool timerN = false; byte i = 0; void setup() { //default states DDRB |= (1<<relayPin); DDRB |= (1<<rLedPin); DDRB |= (1<<gLedPin); PORTB &= ~(1<<relayPin);//relay off PORTB &= ~(1<<rLedPin);//red led off PORTB |= (1<<gLedPin);//green led on /* //fordebug Serial.begin(9600); Serial.println("Start | "+String(millis())); //*/ /* //fordebug without ir receiver pinMode(5, INPUT); pinMode(6, INPUT); //*/ } void shutDown(){ relayState = true; PORTB |= (1<<relayPin); PORTB &= ~(1<<gLedPin); PORTB |= (1<<rLedPin); //Serial.println("turining off |"+String(millis())); } void startUp(){ relayState = false; PORTB &= ~(1<<relayPin); PORTB |= (1<<gLedPin); PORTB &= ~(1<<rLedPin); //Serial.println("turining on |"+String(millis())); } void loop() { unsigned long irCode = listenForIR(); // Wait for an IR Code //Serial.println("ir code: "+String(irCode)); if(irCode == 3359105948){//green button //Serial.println("Pressed green btn |"+String(millis())); if(timer == 0){//on off mode if(relayState == true){ startUp(); }else{ shutDown(); } }else{//cancel timer mode timer = 0; PORTB &= ~(1<<rLedPin);//turn off red led //Serial.println("timer canceled |"+String(millis())); } }//end green btn if(3359101868 == irCode){//red btn //Serial.println("pressed red btn |"+String(millis())); if(timer == 0){ if(relayState == 0){ timer = millis(); //Serial.println("timer started |"+String(millis())); }/*else{ Serial.println("already shutdown |"+String(millis())); } //*/ }else{//changing time mode timerN = !timerN; if(timerN){ //Serial.println("change 30sec |"+String(millis())); shift = timeN1;//30min }else{ //Serial.println("change 60sec |"+String(millis())); shift = timeN2;//60min } } }//end red btn } // loop end void checkTimer(){ unsigned long time = millis(); if(time - previousMillis >= timerInterval || previousMillis > time ) { previousMillis =time; timer1(); } } unsigned long listenForIR() {// IR receive code byte currentpulse = 0; // index for pulses we're storing unsigned long irCode = 0; // Wait for an IR Code irCode = irCode << 1; while (true) { unsigned int pulse = 0;// temporary storage timing //bool true (HIGH) while (IRpin_PIN & _BV(IRpin)) { // got a high pulse (99% standby time have HIGH) if(++i > 150){//check timer every 150 iterations (high frequency break ir code timing) i = 0; checkTimer(); } pulse++; delayMicroseconds(RESOLUTION); if (((pulse >= MAXPULSE) && (currentpulse != 0)) || currentpulse == NUMPULSES ) { return irCode; } } //make irCode irCode = irCode << 1; if ((pulse * RESOLUTION) > 0 && (pulse * RESOLUTION) < 500) { irCode |= 0; }else { irCode |= 1; } currentpulse++; pulse = 0; //bool false (LOW) while (!(IRpin_PIN & _BV(IRpin))) {//wait before new pulse //checkTimer(); pulse++; delayMicroseconds(RESOLUTION); if (pulse >= MAXPULSE || currentpulse == NUMPULSES ) { //Serial.println(irCode); return irCode; } } }//end while(1) }//end listenForIR //executing every timerInverval void timer1() { if(timer != 0){ if(timerN == true){//timeN1 or timeN2 PORTB |= (1<<rLedPin); }else{//blinking 30min PORTB ^= (1<<rLedPin);//invert } //Serial.println(String((timer+shift - millis())/1000)); } if(timer != 0 &&(timer+shift < millis() || timer > millis())){ timer = 0; shutDown(); } }
I almost didn’t take photos, but what is there, that is:
A photo
Because of another pinout of the spare TSOP in the second version, I had to transfer it to the wiring and fix it with glue (later I just attached it to the case).