Jednoduchý prijímač diaľkového IR ovládania
Zo stránky SensorWiki
Záverečný projekt predmetu MIPS / LS2024 - Meno Priezvisko
Zadanie
Zostrojte a naprogramujte ovladanie škrtiacej klapky pomocou plynového pedálu.
Literatúra:
Analýza a opis riešenia
Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami...
Nezabudnite doplniť schému zapojenia!
Algoritmus a program
Algoritmus programu je....
#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
Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia. Na konci uvádzame fotku záverečnej obrazovky pred resetom. Vypísaný je tu priemerný čas a najlepší čas.
Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.