Jednoduchý prijímač diaľkového IR ovládania: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
|||
Riadok 1: | Riadok 1: | ||
Záverečný projekt predmetu MIPS / LS2024 - ''' | Záverečný projekt predmetu MIPS / LS2024 - '''Kateryna Buzko''' | ||
Aktuálna revízia z 15:16, 11. jún 2024
Záverečný projekt predmetu MIPS / LS2024 - Kateryna Buzko
Zadanie
Zostrojte a naprogramujte ovladanie RGB led diódy pomocou ovládača.
Literatúra:
Analýza a opis riešenia
Projekt som začala riesiť zapojením hardwaru-ten je veľmi jednoduchý: RGB-ledka, IR-prijímač, rezistory na 220 Ohm a samozrejme káble. Následne som začala pracovať nad kodom. Pôvodne som planovala urobiť kód pomocou knižnice "IR.remote", ale kód nešiel spústiť a nevedla som opraviť chybu. Potom som spravila kód pomocou vnorených knižníc AVR štúdia, ten už išiel spustiť, reagoval na IR vysielanie, ale farby ledky sa nemenili. Po dlhodobom snažení opraviť chybu bolo prijaté riešenie trošku zijednodušiť projekt a namiesto správneho spočítavania impulzov každého tlačidlka funkcia zmien farieb bola zadaná akokeby manuálne. Čiže v konečnom dôsledku sa deje to, že prijímač zachýtavá každý signál od ovládača, ale prepínanie prebieha náhodným spôsobom s ľubovoľnými tlačidkami: môže sa farba zasvetiť, môže isť niekoľko krat za sebou, môže sa zhasnuť a s ďalším tlačením sa zmení na inú farbu atď.
Táto schéma zobrazuje zapojenie infračerveného prijímača (IR receiver) TSOP382 a troch LED diód (LED 1, LED 2, LED 3) na Arduino r3 s čipom Atmega328p. LED diódy sú pripojené k digitálnym pinom Arduino (PIN 9, PIN 10, PIN 11) cez rezistory (R1, R2, R3) s hodnotou 200 Ω, pričom katódy (záporné vývody) všetkých LED diód sú pripojené k zemi (GND). IR prijímač TSOP382 má tri piny: GND (uzemnenie), výstupný pin (pripojený k digitálnemu pinu 2 na Arduine) a VCC (pripojený k +5V). LED diódy sú ovládané digitálnymi výstupmi Arduino, pričom rezistory R1, R2 a R3 zabezpečujú obmedzenie prúdu cez LED diódy, aby nedošlo k ich poškodeniu. IR prijímač prijíma infračervené signály a konvertuje ich na digitálny signál, ktorý je potom odoslaný do digitálneho pinu 2 na Arduine. Toto zapojenie umožňuje Arduinu prijímať signály z infračerveného diaľkového ovládača a reagovať na ne
Algoritmus a program
Celý kód je napísaný v jednom .c súbore – na spustenie treba 2 externé knižnice.
"Manuálna" zmena bola vykonaná v riadkoch "ir_code<<=1" a "ir_code=(ir_code<<1)|1" IF cyklu. Namiesto hodnôt impulzov pre každé tlačidko nastavila som funkciu "ir_code" číselne pre tri farby: ir_code=0xFFA25D, ir_code=0xFF629D a ir_code=0xFFE21D.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include "uart.h"
// #define F_CPU 16000000UL
// #define BAUD 9600
// Define button codes (example values, replace with actual values from your remote)
#define RED_BUTTON 0xFFA25D
#define GREEN_BUTTON 0xFF629D
#define BLUE_BUTTON 0xFFE21D
#define OFF_BUTTON 0xFF22DD
#define IRLED PD2
#define toggleBIT(reg, bit) ((reg) ^= (1 << (bit))) //PREPNUTIE STAVU
#define setBIT(reg, bit) ((reg) |= (1 << (bit))) //JEDNA
#define clearBIT(reg, bit) ((reg) &= ~(1 << (bit))) //NULAs
volatile uint32_t ir_code = 0;
volatile uint8_t bit_count = 0;
void initIRReceiver(void);
void initRGBLED(void);
void setColor(uint8_t red, uint8_t green, uint8_t blue);
void handleIRCode(uint32_t code);
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
ISR(INT0_vect) {
// Simple state machine to decode the IR signal
static uint8_t last_edge = 0;
uint8_t edge = (PIND & (1 << PIND2)) >> PIND2;
uint16_t duration = TCNT1;
TCNT1 = 0;
if (edge == last_edge) return;
last_edge = edge;
if (duration > 10000) { // Header
ir_code = 0;
bit_count = 0;
} else if (duration > 0 && duration < 100) { // Logical 0
ir_code = 0xFFA25D ;
bit_count++;
} else if (duration > 100 && duration < 200) { // Logical 1
ir_code = 0xFF629D;
bit_count++;
}
else if (duration > 200 && duration < 300) { // Logical 1
ir_code = 0xFFE21D;
bit_count++;
}
if (bit_count >= 32) {
handleIRCode(ir_code);
printf("IR Code: %08lX\n",ir_code);
ir_code = 0;
bit_count = 0;
}
}
void initIRReceiver(void) {
clearBIT(PORTD,IRLED);
clearBIT(DDRD,IRLED);
EICRA |= (1 << ISC00); // Any logical change on INT0 triggers interrupt
EIMSK |= (1 << INT0); // Enable external interrupt INT0
// Timer1 initialization
TCCR1B |= (1 << CS11); // Prescaler 8
TCNT1 = 0; // Initialize counter
}
void initRGBLED(void) {
// Set PB1, PB2, and PB3 as output (PWM)
DDRB |= (1 << PB1) | (1 << PB2) | (1 << PB3);
// Setup Timer1 for Fast PWM mode on PB1 and PB2
TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TCCR1B |= (1 << WGM12) | (1 << WGM13);
ICR1 = 255; // TOP value for 8-bit PWM
// Setup Timer2 for Fast PWM mode on PB3
TCCR2A |= (1 << COM2A1) | (1 << WGM20) | (1 << WGM21);
TCCR2B |= (1 << CS21); // Prescaler 8
}
void setColor(uint8_t red, uint8_t green, uint8_t blue) {
OCR1A = red; // Set PWM value for PB1 (Red)
OCR1B = green; // Set PWM value for PB2 (Green)
OCR2A = blue; // Set PWM value for PB3 (Blue)
}
void handleIRCode(uint32_t code) {
switch(code) {
case RED_BUTTON:
printf("Red Button Pressed\n");
setColor(255, 0, 0); // Red
break;
case GREEN_BUTTON:
printf("Green Button Pressed\n");
setColor(0, 255, 0); // Green
break;
case BLUE_BUTTON:
printf("Blue Button Pressed\n");
setColor(0, 0, 255); // Blue
break;
case OFF_BUTTON:
printf("Off Button Pressed\n");
setColor(0, 0, 0); // Off
break;
default:
printf("Unknown Button Pressed\n");
break;
}
}
int main(void) {
uart_init();
stdout = &mystdout;
initIRReceiver();
initRGBLED();
printf("System Initialized\n");
sei(); //globalne interupty
while (1)
{
printf("IR Code: %08lX\r",ir_code);
}
}
/* ************************************************************************* */
/* FileName: uart.c */
/* ************************************************************************* */
#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"
void uart_init( void )
{
// for different BAUD rate change the project settings, or uncomment
// following two lines:
// #undef BAUD // avoid compiler warning
#include <util/setbaud.h> // requires defined BAUD
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X // defined in setbaud.h
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
}
int uart_putc( char c, FILE *stream )
{
if (c == '\n')
uart_putc('\r',stream);
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
UDR0 = c;
return 0;
}
void uart_puts(const char *s, FILE *stream)
{
while(*s)
{
uart_putc(*s++, stream);
}
}
char uart_getc(void)
{
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
return UDR0;
}
void delay(int delay) // vlastna funkcia pre dlhsie casy
{
for (int i=1; i<=delay; i++)
_delay_ms(1);
}
/* ************************************************************************* */
/* FileName: uart.h */
/* ************************************************************************* */
#define LED PB5 // internal on-board LED
/* na testovanie su uz zadefinovane */
// bit_is_set(PINB, SW1)
// bit_is_clear(PINB, SW1)
/* na cakanie su preddefinovane slucky */
// loop_until_bit_is_set(PINB, SW1); // cakanie na uvolnenie tlacitka
// loop_until_bit_is_clear(PINB, SW1); // cakanie na stlacenie tlacitka
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#ifndef UART_H_
#define UART_H_
#include <stdio.h>
#define BAUD_PRESCALE 103 // vzor?ek z datasheetu
void hw_init( void );
void uart_init( void );
/* Following definition is compatible with STDIO.H, for more
* information see https://www.appelsiini.net/2011/simple-usart-with-avr-libc/
*/
int uart_putc( char c, FILE *stream );
void uart_puts( const char *s, FILE *stream);
char uart_getc( void );
void delay(int delay);
#endif /* UART_H_ */
Zdrojový kód: zdrojaky.zip
Overenie
Ako vidíme, program ozaj funguje tak, že prijímač zachytáva všetky signály od ovládača, no prepínanie prebieha náhodne. V danom videu sa podarilo zachýtiť sekvenciu zmien farieb a následné zhasnutie ledky.
Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.