Operácie

Infračervený vypínač s ATtiny45: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
StudentMIPS (diskusia | príspevky)
Riadok 35: Riadok 35:
<tabs>
<tabs>
<tab name="Hlavný kód"><syntaxhighlight  lang="c++" style="background: LightYellow;">
<tab name="Hlavný kód"><syntaxhighlight  lang="c++" style="background: LightYellow;">
/*
Simple NEC IR sender with button on ATmega328P (Arduino Uno hardware) in AVR C
Wiring:
  - IR LED anode via 100? resistor to PD3, cathode to GND
  - Pushbutton: one side to PD2, other to GND (use internal pull-up)
  - Indicator LED anode via 330? resistor to PB5 (Arduino pin 13), cathode to GND
  - F_CPU = 16 MHz
*/
#define F_CPU 16000000UL
#define F_CPU 16000000UL
#define BAUD 9600
#include <avr/io.h>
#include <avr/io.h>
#include <util/delay.h>
#include <util/delay.h>
#include "uart.h"
#include <stdio.h>


FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
// --- Definícia pinov ---
#define IR_DDR  DDRD
#define IR_PORT  PORTD
#define IR_PIN  3      // PD3 pre IR LED


void inicializaciaADC() {
#define BTN_DDR  DDRD
    ADMUX = (1 << REFS0); // Referenčné napätie AVCC
#define BTN_PORT  PORTD
    ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
#define BTN_PINR  PIND
}
#define BTN_PIN  2      // PD2 pre tlačidlo


uint16_t citanieADC(uint8_t kanal) {
#define LED_DDR  DDRB
    ADMUX = (ADMUX & 0xF0) | kanal;
#define LED_PORT  PORTB
    ADCSRA |= (1 << ADSC);
#define LED_PIN  5      // PB5 (Arduino pin 13) pre indikáciu
    while (ADCSRA & (1 << ADSC));
    return ADC;
}


void inicializaciaServa() {
// Časovania protokolu NEC (v mikrosekundách)
    DDRB |= (1 << PB1) | (1 << PB2); // Servá 1 a 2 (TIMER1)
#define NEC_HDR_MARK  9000
    DDRD |= (1 << PD6) | (1 << PD5); // Servá 3 a 4 (TIMER0)
#define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK  562
#define NEC_ONE_SPACE 1688
#define NEC_ZERO_SPACE 562
#define NEC_RPT_SPACE 2250


    ICR1 = 39999; // PWM 50 Hz pre TIMER1 (16-bit)
// 32-bitový kód, ktorý sa bude odosielať
    TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
#define MY_CODE 0xBF40FF00
    TCCR1B |= (1 << WGM12) | (1 << WGM13) | (1 << CS11); // Fast PWM, prescaler 8


    TCCR0A |= (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00);
// Funkcia na vyslanie "mark" (38 kHz nosnej) po dobu "us" µs
    TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64 (8-bit PWM)
static void mark(uint16_t us) {
    // kmitočet ~38 kHz: perioda ~26 µs, polperióda ~13 µs
    uint16_t cycles = us / 26;
    while (cycles--) {
        IR_PORT |= (1 << IR_PIN);
        _delay_us(13);
        IR_PORT &= ~(1 << IR_PIN);
        _delay_us(13);
    }
}
}


int main(void) {
// Funkcia na vyslanie "space" (vypnutá LED) po dobu "us" µs
     uart_init();
static void space(uint16_t us) {
     stdout = &mystdout;
     IR_PORT &= ~(1 << IR_PIN);
     while (us--) {
        _delay_us(1);
    }
}


     inicializaciaADC();
// Funkcia na odoslanie 32-bitového NEC kódu
     inicializaciaServa();
static void sendNEC(uint32_t code) {
    // úvodný rámec (header)
    mark(NEC_HDR_MARK);
    space(NEC_HDR_SPACE);
    // odosielanie bitov LSB ako prvé
    for (uint8_t i = 0; i < 32; i++) {
        mark(NEC_BIT_MARK);
        if (code & 1) {
            space(NEC_ONE_SPACE);
        } else {
            space(NEC_ZERO_SPACE);
        }
        code >>= 1;
    }
    // záverečný "mark"
     mark(NEC_BIT_MARK);
     IR_PORT &= ~(1 << IR_PIN);
}


    uint16_t natocenie1 = 2000, natocenie2 = 2500;
int main(void) {
     uint16_t natocenie3 = 128, natocenie4 = 128;
     // nastavenie GPIO: IR LED výstup
 
     IR_DDR |= (1 << IR_PIN);
     OCR1A = natocenie1;
     // tlačidlo vstup s interným pull-up
     OCR1B = natocenie2;
     BTN_DDR &= ~(1 << BTN_PIN);
     OCR0A = natocenie3;
     BTN_PORT |= (1 << BTN_PIN);
     OCR0B = natocenie4;
     // indikácia LED výstup
 
     LED_DDR |= (1 << LED_PIN);
     const uint16_t krok = 80,krok2=10;        // rýchlosť pohybu, krok2 musí byt kvôli TIMER0 mat menšiu veľkosť (8-bit PWM)
     LED_PORT &= ~(1 << LED_PIN);
     const uint16_t dead_zone = 50;
     const uint16_t min_PWM1_s1 = 1500, max_PWM1_s1 = 4200,min_PWM1_s2 = 1500, max_PWM1_s2 = 4200; //nastavenie polomeru otáčania pre každé servo zvlášť pri Timer1
    const uint16_t min_PWM0_s3 = 60, max_PWM0_s3 = 180,min_PWM0_s4 = 60, max_PWM0_s4 = 180;//nastavenie polomeru otáčanie pre každé servo zvlášť pri Timer0


     while (1) {
     while (1) {
        uint16_t adcX1 = citanieADC(0);
         // čakanie na stlačenie tlačidla (aktívne LOW)
        uint16_t adcY1 = citanieADC(1);
         if (!(BTN_PINR & (1 << BTN_PIN))) {
        uint16_t adcX2 = citanieADC(2);
            _delay_ms(50); // eliminácia odrazu (debounce)
        uint16_t adcY2 = citanieADC(3);
            if (!(BTN_PINR & (1 << BTN_PIN))) {
 
                // odoslanie NEC kódu
         // vypis pomocou UART
                sendNEC(MY_CODE);
        printf("Joystick1 X:%4d  Y:%4d  | Joystick2 X:%4d  Y:%4d\n", adcX1, adcY1, adcX2, adcY2);
                // krátke zobrazenie výsledku na LED
 
                LED_PORT |= (1 << LED_PIN);
        // Servo 1
                _delay_ms(200);
         if (adcX1 < (512 - dead_zone) && (natocenie1 > min_PWM1_s1))  
                LED_PORT &= ~(1 << LED_PIN);
{
                // počkaj na uvoľnenie tlačidla
natocenie1 -= krok;
                while (!(BTN_PINR & (1 << BTN_PIN)));
}
                _delay_ms(50);
        else if (adcX1 > (512 + dead_zone) && (natocenie1 < max_PWM1_s1))  
            }
{
         }
natocenie1 += krok;
}
        OCR1A = natocenie1;
 
        // Servo 2
        if (adcY1 < (512 - dead_zone) && (natocenie2 > min_PWM1_s2))  
{
natocenie2 -= krok;
}
        else if (adcY1 > (512 + dead_zone) && (natocenie2 < max_PWM1_s2))  
{
natocenie2 += krok;
}
        OCR1B = natocenie2;
 
        // Servo 3
        if (adcX2 < (512 - dead_zone) && (natocenie3 > min_PWM0_s3))
{
natocenie3 -= krok2;
}
        else if (adcX2 > (512 + dead_zone) && (natocenie3 < max_PWM0_s3))  
{
natocenie3 += krok2;
}
        OCR0A = natocenie3;
 
        // Servo 4
        if (adcY2 < (512 - dead_zone) && (natocenie4 > min_PWM0_s4))
{
natocenie4 -= krok2;
}
        else if (adcY2 > (512 + dead_zone) && (natocenie4 < max_PWM0_s4))
{
natocenie4 += krok2;
}
         OCR0B = natocenie4;
 
        _delay_ms(10); // pre rýchlejšie reakcie 10ms
     }
     }
    return 0;
}
}


</syntaxhighlight ></tab>
</syntaxhighlight ></tab>

Verzia z 20:55, 11. jún 2025

Záverečný projekt predmetu MIPS / LS2025 - Meno Priezvisko


Zadanie

Cieľom môjho zadania bolo vytvoriť program, ktorý umožní vysielať špecialny kód, ktorý budeme vysielať pomocou IR diody.


Vývojová doska ACROB.

Literatúra:


Analýza a opis riešenia

Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami... Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.

Celkový pohľad na zariadenie.

Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.

Schéma zapojenia.


Algoritmus a program

Algoritmus programu využíva toto a toto, základné funkcie sú takéto a voláma ich tuto... Výpis kódu je nižšie...


/*
Simple NEC IR sender with button on ATmega328P (Arduino Uno hardware) in AVR C
Wiring:
  - IR LED anode via 100? resistor to PD3, cathode to GND
  - Pushbutton: one side to PD2, other to GND (use internal pull-up)
  - Indicator LED anode via 330? resistor to PB5 (Arduino pin 13), cathode to GND
  - F_CPU = 16 MHz
*/

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// --- Definícia pinov ---
#define IR_DDR   DDRD
#define IR_PORT  PORTD
#define IR_PIN   3       // PD3 pre IR LED

#define BTN_DDR   DDRD
#define BTN_PORT  PORTD
#define BTN_PINR  PIND
#define BTN_PIN   2      // PD2 pre tlačidlo

#define LED_DDR   DDRB
#define LED_PORT  PORTB
#define LED_PIN   5      // PB5 (Arduino pin 13) pre indikáciu

// Časovania protokolu NEC (v mikrosekundách)
#define NEC_HDR_MARK  9000
#define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK   562
#define NEC_ONE_SPACE 1688
#define NEC_ZERO_SPACE 562
#define NEC_RPT_SPACE 2250

// 32-bitový kód, ktorý sa bude odosielať
#define MY_CODE 0xBF40FF00

// Funkcia na vyslanie "mark" (38 kHz nosnej) po dobu "us" µs
static void mark(uint16_t us) {
    // kmitočet ~38 kHz: perioda ~26 µs, polperióda ~13 µs
    uint16_t cycles = us / 26;
    while (cycles--) {
        IR_PORT |= (1 << IR_PIN);
        _delay_us(13);
        IR_PORT &= ~(1 << IR_PIN);
        _delay_us(13);
    }
}

// Funkcia na vyslanie "space" (vypnutá LED) po dobu "us" µs
static void space(uint16_t us) {
    IR_PORT &= ~(1 << IR_PIN);
    while (us--) {
        _delay_us(1);
    }
}

// Funkcia na odoslanie 32-bitového NEC kódu
static void sendNEC(uint32_t code) {
    // úvodný rámec (header)
    mark(NEC_HDR_MARK);
    space(NEC_HDR_SPACE);
    // odosielanie bitov LSB ako prvé
    for (uint8_t i = 0; i < 32; i++) {
        mark(NEC_BIT_MARK);
        if (code & 1) {
            space(NEC_ONE_SPACE);
        } else {
            space(NEC_ZERO_SPACE);
        }
        code >>= 1;
    }
    // záverečný "mark"
    mark(NEC_BIT_MARK);
    IR_PORT &= ~(1 << IR_PIN);
}

int main(void) {
    // nastavenie GPIO: IR LED výstup
    IR_DDR |= (1 << IR_PIN);
    // tlačidlo vstup s interným pull-up
    BTN_DDR &= ~(1 << BTN_PIN);
    BTN_PORT |= (1 << BTN_PIN);
    // indikácia LED výstup
    LED_DDR |= (1 << LED_PIN);
    LED_PORT &= ~(1 << LED_PIN);

    while (1) {
        // čakanie na stlačenie tlačidla (aktívne LOW)
        if (!(BTN_PINR & (1 << BTN_PIN))) {
            _delay_ms(50);  // eliminácia odrazu (debounce)
            if (!(BTN_PINR & (1 << BTN_PIN))) {
                // odoslanie NEC kódu
                sendNEC(MY_CODE);
                // krátke zobrazenie výsledku na LED
                LED_PORT |= (1 << LED_PIN);
                _delay_ms(200);
                LED_PORT &= ~(1 << LED_PIN);
                // počkaj na uvoľnenie tlačidla
                while (!(BTN_PINR & (1 << BTN_PIN)));
                _delay_ms(50);
            }
        }
    }
    return 0;
}
#include "uart.h"

#include <avr/io.h>
#include <util/setbaud.h>

#define F_CPU		16000000UL
#define BAUDRATE       9600
#define BAUD_PRESCALE  (((F_CPU / (BAUDRATE * 16UL))) - 1)  // vzor?ek z datasheetu

void uart_init( void ) 
{
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
	
	UBRR0 = (unsigned char)BAUD_PRESCALE;                 // Set baud rate: Load the UBRR register

    UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);                     // Set format: 8data, 1stop bit 

    UCSR0B = (1 << RXEN0) | (1 << TXEN0);                 // Enable receiver and transmitter

#if USE_2X
    UCSR0A |= _BV(U2X0);
#else
    UCSR0A &= ~(_BV(U2X0));
#endif

    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
    UCSR0B = _BV(RXEN0) | _BV(TXEN0);   /* Enable RX and TX */
}


void uart_putc(char c) 
{
   if (c == '\n') 
    {
       uart_putc('\r');
    }
   loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
   UDR0 = c;
}


void uart_puts(const char *s)
{
  /* toto je vasa uloha */
}

char uart_getc(void) {
    loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
    return UDR0;
}
#ifndef UART_H_
#define UART_H_
#define F_CPU		16000000UL
#define BAUD       9600
#define BAUD_PRESCALE  (((F_CPU / (BAUD * 16UL))) - 1)  // vzor?ek z datasheetu

void uart_init( void );
     
void uart_putc( char c );
void uart_puts( const char *s );

char uart_getc( void );

#endif /* UART_H_ */

Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x zdrojaky.zip:

Zdrojový kód: zdrojaky.zip

Overenie

Ako ste overili funkciu, napríklad... 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 hotového zariadenia.

Aplikácia.

Video:



Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.