Operácie

Ovládanie vyklápacích svetiel: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
StudentMIPS (diskusia | príspevky)
Riadok 18: Riadok 18:
== Analýza  a opis riešenia ==
== Analýza  a opis riešenia ==


Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami...
Hlavnou úlohou systému je riadiť pohyb výklopných svetiel nezávisle od seba. Každé svetlo je ovládané dvoma výstupmi – jeden pre pohyb hore a druhý pre pohyb dole. Týmto spôsobom je možné svetlá zdvíhať, spúšťať a vykonávať rôzne blikacie sekvencie. Svetlá je možné ovládať dvoma spôsobmi – mechanickým tlačidlom alebo príkazmi cez UART.
Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.  


[[Súbor:GeminiAI-image3.jpg|400px|thumb|center|Celkový pohľad na zariadenie.]]
'''Použite komponenty:'''
*Tlačidlo v aute
*Motorčeky na vyklápanie svetiel
*4-Kanálová relé doska s optočlenom


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.
[[Súbor:Rele_doska.jpg|400px|thumb|center|Relé doska]]


[[Súbor:GeminiAI-image2.jpg|400px|thumb|center|Schéma zapojenia.]]
Na detekciu klikov a časovanie pohybov sa využíva časovač TIMER0 v režime CTC, ktorý generuje prerušovanie každú 1 ms. Tým vzniká softvérový časovač pomocou premennej ''milliseconds''.
 
'''Program rozlišuje:'''
*Jedno kliknutie – slúži na zapnutie alebo vypnutie svetiel (pohyb hore alebo dole).
*Dvojklik – spúšťa animovanú sekvenciu bliknutia svetiel.
*UART príkazy – umožňujú spustiť rôzne preddefinované sekvencie
 
Funkcie pre ovládanie svetiel sú implementované v súbore sequences.c. Tieto funkcie priamo nastavujú piny výstupov podľa požadovaného smeru pohybu a obsahujú časové oneskorenia, ktoré simulujú fyzický pohyb svetiel.
 
'''Schéma zapojenia:'''
 
[[Súbor:SchemaZapojeniaWink.jpg|400px|thumb|center|Schéma zapojenia.]]




=== Algoritmus a program ===
=== Algoritmus a program ===


Algoritmus programu využíva toto a toto, základné funkcie sú takéto a voláma ich tuto...  
Program začína inicializáciou periférií:
Výpis kódu je nižšie...
*Nastavenie vstupného pinu pre tlačidlo s pull-up rezistorom.
*Nastavenie výstupných pinov pre ovládanie svetiel.
*Spustenie UART a časovača TIMER0.
*Povolenie globálnych prerušení.
 
'''Hlavná slučka vykonáva:'''
#Sleduje stav tlačidla, používa debounce a detekciu zmeny stavu.
#Rozlišuje jedno a dvojité kliknutie podľa časového odstupu medzi klikmi.
#Ovláda svetlá – pri jednom kliknutí sa svetlá zapnú/vypnú, pri dvojkliku sa spustí blikacia sekvencia.
#Spracováva znaky z UART – ak bol prijatý znak, vykoná sa príslušná funkcia




<tabs>
<tabs>
<tab name="AVR C-code"><syntaxhighlight  lang="c++" style="background: LightYellow;">
<tab name="main.c"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#define F_CPU 16000000UL
#define BAUD 9600
 
#include <avr/io.h>
#include "uart.h"
#include "sequences.h"
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
 
// Pin Definitions
#define SWITCH  PD2
#define L_UP    PB3
#define R_UP    PD5
#define L_DOWN  PB4
#define R_DOWN  PD6
 
// Timing Constants
#define BUTTON_TIME  500  // button wait time for double click
#define DEBOUNCE_DELAY 50  // debounce duration
 
// Headlight State
HeadlightStatus headlights = {0, 0};
 
// Toggle Pattern Tracking
int lastSwitchState = 1;
int firstToggleState = 1;
volatile uint32_t firstToggleTime = 0;
volatile uint8_t toggleSequenceActive = 0;
volatile uint8_t handledSequence = 0;
 
// Millisecond Counter
volatile uint32_t milliseconds = 0;
 
// Timer Setup
void setup_timer0() {
TCCR0A |= (1 << WGM01);            // CTC
OCR0A = 249;                      // 1ms
TIMSK0 |= (1 << OCIE0A);          // Enable interrupt
TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64
}
 
ISR(TIMER0_COMPA_vect) {
milliseconds++;
}
 
unsigned long millis() {
unsigned long ms;
uint8_t oldSREG = SREG;
cli();
ms = milliseconds;
SREG = oldSREG;
return ms;
}
 
// Debounce
uint8_t debounceSwitch(uint8_t pin) {
uint8_t stableState = (PIND & (1 << pin)) ? 1 : 0;
_delay_ms(DEBOUNCE_DELAY);
uint8_t newState = (PIND & (1 << pin)) ? 1 : 0;
return (stableState == newState) ? newState : stableState;
}
 
// Main Loop
int main(void) {
// Switch input
DDRD &= ~(1 << SWITCH);
PORTD |= (1 << SWITCH); // Pull-up
 
// Outputs
DDRB |= (1 << L_UP) | (1 << L_DOWN);
DDRD |= (1 << R_UP) | (1 << R_DOWN);
 
uart_init();
setup_timer0();
sei();
stop();
 
while (1) {
int current = debounceSwitch(SWITCH);
unsigned long now = millis();
 
if (current != lastSwitchState) {
if (!toggleSequenceActive) {
toggleSequenceActive = 1;
handledSequence = 0;
firstToggleState = lastSwitchState;
firstToggleTime = now;
} else if ((now - firstToggleTime) <= (BUTTON_TIME - DEBOUNCE_DELAY) && current == firstToggleState) {
if (firstToggleState == 1) {
AlternateWink();
} else {
Wink();
}
handledSequence = 1;
toggleSequenceActive = 0;
}
lastSwitchState = current;
}
 
if (toggleSequenceActive && !handledSequence && (now - firstToggleTime) > (BUTTON_TIME - DEBOUNCE_DELAY)) {
toggleSequenceActive = 0;
if (lastSwitchState == 0 && !areHeadlightsUp()) {
raiseHeadlights();
uart_puts("ON\n");
} else if (lastSwitchState == 1 && areHeadlightsUp()) {
lowerHeadlights();
uart_puts("OFF\n");
}
}
 
if (!toggleSequenceActive && !handledSequence) {
if (current == 0 && !areHeadlightsUp()) {
raiseHeadlights();
uart_puts("ON\n");
} else if (current == 1 && areHeadlightsUp()) {
lowerHeadlights();
uart_puts("OFF\n");
}
}
 
if (UCSR0A & (1 << RXC0)) {
char command = uart_getc();
 
switch (command) {
case 'M':
if (areHeadlightsUp()) MexicanWink();
else AlternateMexicanWink();
break;
 
case 'W':
if (areHeadlightsUp()) Wink();
else AlternateWink();
break;
 
case 'L':
WinkLeft();
break;
 
case 'R':
WinkRight();
break;
}
}
}
}
</syntaxhighlight ></tab>
<tab name="sequences.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#ifndef SEQUENCES_H
#define SEQUENCES_H
 
#include <stdint.h>
 
typedef struct {
int leftUp  : 1;
int rightUp : 1;
} HeadlightStatus;
 
void moveHeadlight(uint8_t side, uint8_t direction);
void raiseHeadlights(void);
void lowerHeadlights(void);
uint8_t areHeadlightsUp(void);
 
void Wink(void);
void AlternateWink(void);
void MexicanWink(void);
void AlternateMexicanWink(void);
void WinkLeft(void);
void WinkRight(void);
 
void stop(void);
 
#endif
</syntaxhighlight ></tab>
<tab name="sequences.c"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#define F_CPU 16000000UL
#define BAUD 9600
 
#include <avr/io.h>
#include <avr/io.h>
#include <util/delay.h>
#include "sequences.h"


int main(void)
#define UP 1
#define DOWN 0
#define LEFT 1
#define RIGHT 0
 
#define L_UP    PB3
#define R_UP    PD5
#define L_DOWN  PB4
#define R_DOWN  PD6
 
#define MOVE_TIME    750
#define SEQUENCE_TIME  150
 
extern HeadlightStatus headlights;
 
static void set_pin(volatile uint8_t *port, uint8_t pin, uint8_t high) {
if (high)
*port |= (1 << pin);
else
*port &= ~(1 << pin);
}
 
void delay(int delay)
{
{
  unsigned int measuredValue;
for (int i=1; i<=delay; i++)
_delay_ms(1);
}
 
void stop() {
set_pin(&PORTB, L_UP, 1);
set_pin(&PORTD, R_UP, 1);
set_pin(&PORTB, L_DOWN, 1);
set_pin(&PORTD, R_DOWN, 1);
}
 
static void stopLeft() {
set_pin(&PORTB, L_UP, 1);
set_pin(&PORTB, L_DOWN, 1);
}
 
static void stopRight() {
set_pin(&PORTD, R_UP, 1);
set_pin(&PORTD, R_DOWN, 1);
}
 
void moveHeadlight(uint8_t side, uint8_t direction) {
if (side == LEFT) {
set_pin(&PORTB, L_UP, !direction);
set_pin(&PORTB, L_DOWN, direction);
headlights.leftUp = direction;
} else {
set_pin(&PORTD, R_UP, !direction);
set_pin(&PORTD, R_DOWN, direction);
headlights.rightUp = direction;
}
}
 
void raiseHeadlights() {
if (!headlights.leftUp || !headlights.rightUp) {
if (!headlights.leftUp) moveHeadlight(LEFT, UP);
if (!headlights.rightUp) moveHeadlight(RIGHT, UP);
delay(MOVE_TIME);
stop();
headlights.leftUp = UP;
headlights.rightUp = UP;
}
}
 
void lowerHeadlights() {
if (headlights.leftUp || headlights.rightUp) {
if (headlights.leftUp) moveHeadlight(LEFT, DOWN);
if (headlights.rightUp) moveHeadlight(RIGHT, DOWN);
delay(MOVE_TIME);
stop();
headlights.leftUp = DOWN;
headlights.rightUp = DOWN;
}
}
 
uint8_t areHeadlightsUp() {
return headlights.leftUp && headlights.rightUp;
}
 
void Wink() {
moveHeadlight(LEFT, DOWN);
delay(MOVE_TIME);
stop();
 
moveHeadlight(LEFT, UP);
moveHeadlight(RIGHT, DOWN);
delay(MOVE_TIME);
stop();
 
moveHeadlight(LEFT, DOWN);
moveHeadlight(RIGHT, UP);
delay(MOVE_TIME);
stop();
 
moveHeadlight(LEFT, UP);
moveHeadlight(RIGHT, DOWN);
delay(MOVE_TIME);
stop();
 
moveHeadlight(RIGHT, UP);
delay(MOVE_TIME);
stop();
 
headlights.leftUp = UP;
headlights.rightUp = UP;
}
 
void AlternateWink() {
moveHeadlight(LEFT, UP);
delay(MOVE_TIME);
stop();
 
moveHeadlight(LEFT, DOWN);
moveHeadlight(RIGHT, UP);
delay(MOVE_TIME);
stop();
 
moveHeadlight(LEFT, UP);
moveHeadlight(RIGHT, DOWN);
delay(MOVE_TIME);
stop();
 
moveHeadlight(LEFT, DOWN);
moveHeadlight(RIGHT, UP);
delay(MOVE_TIME);
stop();
 
moveHeadlight(RIGHT, DOWN);
delay(MOVE_TIME);
stop();
 
headlights.leftUp = DOWN;
headlights.rightUp = DOWN;
}
 
void MexicanWink() {
for (int i = 0; i < 2; i++) {
moveHeadlight(LEFT, DOWN);
delay(SEQUENCE_TIME);
moveHeadlight(RIGHT, DOWN);
delay(MOVE_TIME - SEQUENCE_TIME);
stopLeft();
delay(SEQUENCE_TIME);
stopRight();
 
moveHeadlight(LEFT, UP);
delay(SEQUENCE_TIME);
moveHeadlight(RIGHT, UP);
delay(MOVE_TIME - SEQUENCE_TIME);
stopLeft();
delay (SEQUENCE_TIME);
stopRight();
}
 
headlights.leftUp = UP;
headlights.rightUp = UP;
}


  while (1)
void AlternateMexicanWink() {
  {
for (int i = 0; i < 2; i++) {
    /*  relax  */ 
moveHeadlight(LEFT, UP);
  }
delay(SEQUENCE_TIME);
moveHeadlight(RIGHT, UP);
delay(MOVE_TIME - SEQUENCE_TIME);
stopLeft();
delay(SEQUENCE_TIME);
stopRight();


  return(0);
moveHeadlight(LEFT, DOWN);
delay(SEQUENCE_TIME);
moveHeadlight(RIGHT, DOWN);
delay(MOVE_TIME - SEQUENCE_TIME);
stopLeft();
delay(SEQUENCE_TIME);
stopRight();
}
 
headlights.leftUp = DOWN;
headlights.rightUp = DOWN;
}
}


void WinkLeft() {
if (headlights.leftUp) {
moveHeadlight(LEFT, DOWN);
delay(MOVE_TIME);
stopLeft();
moveHeadlight(LEFT, UP);
} else {
moveHeadlight(LEFT, UP);
delay(MOVE_TIME);
stopLeft();
moveHeadlight(LEFT, DOWN);
}
delay(MOVE_TIME);
stopLeft();
}
void WinkRight() {
if (headlights.rightUp) {
moveHeadlight(RIGHT, DOWN);
delay(MOVE_TIME);
stopRight();
moveHeadlight(RIGHT, UP);
} else {
moveHeadlight(RIGHT, UP);
delay(MOVE_TIME);
stopRight();
moveHeadlight(RIGHT, DOWN);
}
delay(MOVE_TIME);
stopRight();
}
</syntaxhighlight ></tab>
</syntaxhighlight ></tab>
<tab name="filename.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
<tab name="uart.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#ifndef UART_H_
#define UART_H_
 
void uart_init( void );
 
void uart_putc( char c );
void uart_puts( const char *s );
 
char uart_getc( void );
 
#endif /* UART_H_ */
</syntaxhighlight ></tab>
<tab name="uart.c"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#define F_CPU 16000000UL
#define BAUD 9600
 
#include <avr/io.h>
#include <avr/io.h>
#include <util/setbaud.h>
void uart_init( void )
{
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif


void adc_init(void);                                   // A/D converter initialization
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
UCSR0B = _BV(RXEN0) | _BV(TXEN0);  /* Enable RX and TX */
}


unsigned int adc_read(char a_pin);
 
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)
{
while (*s) {
uart_putc(*s++);
}
}
 
char uart_getc(void) {
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
return UDR0;
}
</syntaxhighlight ></tab>
</syntaxhighlight ></tab>
</tabs>


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

Verzia z 22:10, 16. máj 2025

Záverečný projekt predmetu MIPS / LS2025 - Martin Lenarth


Zadanie

Cieľom bolo navrhnúť mikropočítačový systém, ktorý reaguje na stlačenie tlačidla a umožňuje riadiť pohyb vyklápacích svetiel na aute. Svetlá sa ovládajú pomocou motorčekov (dva smery pohybu), a to buď:

  • pomocou jednoduchého alebo dvojitého zatlačenia tlačidla, alebo
  • pomocou príkazov cez UART (sériová linka) z počítača
Arduino NANO

Literatúra:


Analýza a opis riešenia

Hlavnou úlohou systému je riadiť pohyb výklopných svetiel nezávisle od seba. Každé svetlo je ovládané dvoma výstupmi – jeden pre pohyb hore a druhý pre pohyb dole. Týmto spôsobom je možné svetlá zdvíhať, spúšťať a vykonávať rôzne blikacie sekvencie. Svetlá je možné ovládať dvoma spôsobmi – mechanickým tlačidlom alebo príkazmi cez UART.

Použite komponenty:

  • Tlačidlo v aute
  • Motorčeky na vyklápanie svetiel
  • 4-Kanálová relé doska s optočlenom
Relé doska

Na detekciu klikov a časovanie pohybov sa využíva časovač TIMER0 v režime CTC, ktorý generuje prerušovanie každú 1 ms. Tým vzniká softvérový časovač pomocou premennej milliseconds.

Program rozlišuje:

  • Jedno kliknutie – slúži na zapnutie alebo vypnutie svetiel (pohyb hore alebo dole).
  • Dvojklik – spúšťa animovanú sekvenciu bliknutia svetiel.
  • UART príkazy – umožňujú spustiť rôzne preddefinované sekvencie

Funkcie pre ovládanie svetiel sú implementované v súbore sequences.c. Tieto funkcie priamo nastavujú piny výstupov podľa požadovaného smeru pohybu a obsahujú časové oneskorenia, ktoré simulujú fyzický pohyb svetiel.

Schéma zapojenia:

Schéma zapojenia.


Algoritmus a program

Program začína inicializáciou periférií:

  • Nastavenie vstupného pinu pre tlačidlo s pull-up rezistorom.
  • Nastavenie výstupných pinov pre ovládanie svetiel.
  • Spustenie UART a časovača TIMER0.
  • Povolenie globálnych prerušení.

Hlavná slučka vykonáva:

  1. Sleduje stav tlačidla, používa debounce a detekciu zmeny stavu.
  2. Rozlišuje jedno a dvojité kliknutie podľa časového odstupu medzi klikmi.
  3. Ovláda svetlá – pri jednom kliknutí sa svetlá zapnú/vypnú, pri dvojkliku sa spustí blikacia sekvencia.
  4. Spracováva znaky z UART – ak bol prijatý znak, vykoná sa príslušná funkcia


<tabs>

#define F_CPU 16000000UL
#define BAUD 9600

#include <avr/io.h>
#include "uart.h"
#include "sequences.h"
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>

// Pin Definitions
#define SWITCH  PD2
#define L_UP    PB3
#define R_UP    PD5
#define L_DOWN  PB4
#define R_DOWN  PD6

// Timing Constants
#define BUTTON_TIME  500   // button wait time for double click
#define DEBOUNCE_DELAY 50  // debounce duration

// Headlight State
HeadlightStatus headlights = {0, 0};

// Toggle Pattern Tracking
int lastSwitchState = 1;
int firstToggleState = 1;
volatile uint32_t firstToggleTime = 0;
volatile uint8_t toggleSequenceActive = 0;
volatile uint8_t handledSequence = 0;

// Millisecond Counter
volatile uint32_t milliseconds = 0;

// Timer Setup
void setup_timer0() {
	TCCR0A |= (1 << WGM01);            // CTC
	OCR0A = 249;                       // 1ms
	TIMSK0 |= (1 << OCIE0A);          // Enable interrupt
	TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64
}

ISR(TIMER0_COMPA_vect) {
	milliseconds++;
}

unsigned long millis() {
	unsigned long ms;
	uint8_t oldSREG = SREG;
	cli();
	ms = milliseconds;
	SREG = oldSREG;
	return ms;
}

// Debounce
uint8_t debounceSwitch(uint8_t pin) {
	uint8_t stableState = (PIND & (1 << pin)) ? 1 : 0;
	_delay_ms(DEBOUNCE_DELAY);
	uint8_t newState = (PIND & (1 << pin)) ? 1 : 0;
	return (stableState == newState) ? newState : stableState;
}

// Main Loop
int main(void) {
	// Switch input
	DDRD &= ~(1 << SWITCH);
	PORTD |= (1 << SWITCH); // Pull-up

	// Outputs
	DDRB |= (1 << L_UP) | (1 << L_DOWN);
	DDRD |= (1 << R_UP) | (1 << R_DOWN);

	uart_init();
	setup_timer0();
	sei();
	stop();

	while (1) {
		int current = debounceSwitch(SWITCH);
		unsigned long now = millis();

		if (current != lastSwitchState) {
			if (!toggleSequenceActive) {
				toggleSequenceActive = 1;
				handledSequence = 0;
				firstToggleState = lastSwitchState;
				firstToggleTime = now;
				} else if ((now - firstToggleTime) <= (BUTTON_TIME - DEBOUNCE_DELAY) && current == firstToggleState) {
				if (firstToggleState == 1) {
					AlternateWink();
					} else {
					Wink();
				}
				handledSequence = 1;
				toggleSequenceActive = 0;
			}
			lastSwitchState = current;
		}

		if (toggleSequenceActive && !handledSequence && (now - firstToggleTime) > (BUTTON_TIME - DEBOUNCE_DELAY)) {
			toggleSequenceActive = 0;
			if (lastSwitchState == 0 && !areHeadlightsUp()) {
				raiseHeadlights();
				uart_puts("ON\n");
				} else if (lastSwitchState == 1 && areHeadlightsUp()) {
				lowerHeadlights();
				uart_puts("OFF\n");
			}
		}

		if (!toggleSequenceActive && !handledSequence) {
			if (current == 0 && !areHeadlightsUp()) {
				raiseHeadlights();
				uart_puts("ON\n");
				} else if (current == 1 && areHeadlightsUp()) {
				lowerHeadlights();
				uart_puts("OFF\n");
			}
		}

		if (UCSR0A & (1 << RXC0)) {
			char command = uart_getc();

			switch (command) {
				case 'M':
				if (areHeadlightsUp()) MexicanWink();
				else AlternateMexicanWink();
				break;

				case 'W':
				if (areHeadlightsUp()) Wink();
				else AlternateWink();
				break;

				case 'L':
				WinkLeft();
				break;

				case 'R':
				WinkRight();
				break;
			}
		}
	}
}
#ifndef SEQUENCES_H
#define SEQUENCES_H

#include <stdint.h>

typedef struct {
	int leftUp  : 1;
	int rightUp : 1;
} HeadlightStatus;

void moveHeadlight(uint8_t side, uint8_t direction);
void raiseHeadlights(void);
void lowerHeadlights(void);
uint8_t areHeadlightsUp(void);

void Wink(void);
void AlternateWink(void);
void MexicanWink(void);
void AlternateMexicanWink(void);
void WinkLeft(void);
void WinkRight(void);

void stop(void);

#endif
#define F_CPU 16000000UL
#define BAUD 9600

#include <avr/io.h>
#include <util/delay.h>
#include "sequences.h"

#define UP 1
#define DOWN 0
#define LEFT 1
#define RIGHT 0

#define L_UP     PB3
#define R_UP     PD5
#define L_DOWN   PB4
#define R_DOWN   PD6

#define MOVE_TIME    750
#define SEQUENCE_TIME   150

extern HeadlightStatus headlights;

static void set_pin(volatile uint8_t *port, uint8_t pin, uint8_t high) {
	if (high)
	*port |= (1 << pin);
	else
	*port &= ~(1 << pin);
}

void delay(int delay)
{
	for (int i=1; i<=delay; i++)
	_delay_ms(1);
}

void stop() {
	set_pin(&PORTB, L_UP, 1);
	set_pin(&PORTD, R_UP, 1);
	set_pin(&PORTB, L_DOWN, 1);
	set_pin(&PORTD, R_DOWN, 1);
}

static void stopLeft() {
	set_pin(&PORTB, L_UP, 1);
	set_pin(&PORTB, L_DOWN, 1);
}

static void stopRight() {
	set_pin(&PORTD, R_UP, 1);
	set_pin(&PORTD, R_DOWN, 1);
}

void moveHeadlight(uint8_t side, uint8_t direction) {
	if (side == LEFT) {
		set_pin(&PORTB, L_UP, !direction);
		set_pin(&PORTB, L_DOWN, direction);
		headlights.leftUp = direction;
		} else {
		set_pin(&PORTD, R_UP, !direction);
		set_pin(&PORTD, R_DOWN, direction);
		headlights.rightUp = direction;
	}
}

void raiseHeadlights() {
	if (!headlights.leftUp || !headlights.rightUp) {
		if (!headlights.leftUp) moveHeadlight(LEFT, UP);
		if (!headlights.rightUp) moveHeadlight(RIGHT, UP);
		delay(MOVE_TIME);
		stop();
		headlights.leftUp = UP;
		headlights.rightUp = UP;
	}
}

void lowerHeadlights() {
	if (headlights.leftUp || headlights.rightUp) {
		if (headlights.leftUp) moveHeadlight(LEFT, DOWN);
		if (headlights.rightUp) moveHeadlight(RIGHT, DOWN);
		delay(MOVE_TIME);
		stop();
		headlights.leftUp = DOWN;
		headlights.rightUp = DOWN;
	}
}

uint8_t areHeadlightsUp() {
	return headlights.leftUp && headlights.rightUp;
}

void Wink() {
	moveHeadlight(LEFT, DOWN);
	delay(MOVE_TIME);
	stop();

	moveHeadlight(LEFT, UP);
	moveHeadlight(RIGHT, DOWN);
	delay(MOVE_TIME);
	stop();

	moveHeadlight(LEFT, DOWN);
	moveHeadlight(RIGHT, UP);
	delay(MOVE_TIME);
	stop();

	moveHeadlight(LEFT, UP);
	moveHeadlight(RIGHT, DOWN);
	delay(MOVE_TIME);
	stop();

	moveHeadlight(RIGHT, UP);
	delay(MOVE_TIME);
	stop();

	headlights.leftUp = UP;
	headlights.rightUp = UP;
}

void AlternateWink() {
	moveHeadlight(LEFT, UP);
	delay(MOVE_TIME);
	stop();

	moveHeadlight(LEFT, DOWN);
	moveHeadlight(RIGHT, UP);
	delay(MOVE_TIME);
	stop();

	moveHeadlight(LEFT, UP);
	moveHeadlight(RIGHT, DOWN);
	delay(MOVE_TIME);
	stop();

	moveHeadlight(LEFT, DOWN);
	moveHeadlight(RIGHT, UP);
	delay(MOVE_TIME);
	stop();

	moveHeadlight(RIGHT, DOWN);
	delay(MOVE_TIME);
	stop();

	headlights.leftUp = DOWN;
	headlights.rightUp = DOWN;
}

void MexicanWink() {
	for (int i = 0; i < 2; i++) {
		moveHeadlight(LEFT, DOWN);
		delay(SEQUENCE_TIME);
		moveHeadlight(RIGHT, DOWN);
		delay(MOVE_TIME - SEQUENCE_TIME);
		stopLeft();
		delay(SEQUENCE_TIME);
		stopRight();

		moveHeadlight(LEFT, UP);
		delay(SEQUENCE_TIME);
		moveHeadlight(RIGHT, UP);
		delay(MOVE_TIME - SEQUENCE_TIME);
		stopLeft();
		delay (SEQUENCE_TIME);
		stopRight();
	}

	headlights.leftUp = UP;
	headlights.rightUp = UP;
}

void AlternateMexicanWink() {
	for (int i = 0; i < 2; i++) {
		moveHeadlight(LEFT, UP);
		delay(SEQUENCE_TIME);
		moveHeadlight(RIGHT, UP);
		delay(MOVE_TIME - SEQUENCE_TIME);
		stopLeft();
		delay(SEQUENCE_TIME);
		stopRight();

		moveHeadlight(LEFT, DOWN);
		delay(SEQUENCE_TIME);
		moveHeadlight(RIGHT, DOWN);
		delay(MOVE_TIME - SEQUENCE_TIME);
		stopLeft();
		delay(SEQUENCE_TIME);
		stopRight();
	}

	headlights.leftUp = DOWN;
	headlights.rightUp = DOWN;
}

void WinkLeft() {
	if (headlights.leftUp) {
		moveHeadlight(LEFT, DOWN);
		delay(MOVE_TIME);
		stopLeft();
		moveHeadlight(LEFT, UP);
	} else {
		moveHeadlight(LEFT, UP);
		delay(MOVE_TIME);
		stopLeft();
		moveHeadlight(LEFT, DOWN);
	}
	delay(MOVE_TIME);
	stopLeft();
}

void WinkRight() {
	if (headlights.rightUp) {
		moveHeadlight(RIGHT, DOWN);
		delay(MOVE_TIME);
		stopRight();
		moveHeadlight(RIGHT, UP);
		} else {
		moveHeadlight(RIGHT, UP);
		delay(MOVE_TIME);
		stopRight();
		moveHeadlight(RIGHT, DOWN);
	}
	delay(MOVE_TIME);
	stopRight();
}
#ifndef UART_H_
#define UART_H_

void uart_init( void );

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

char uart_getc( void );

#endif /* UART_H_ */
#define F_CPU 16000000UL
#define BAUD 9600

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

void uart_init( void )
{
	UBRR0H = UBRRH_VALUE;
	UBRR0L = UBRRL_VALUE;

	#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)
{
	while (*s) {
		uart_putc(*s++);
	}
}

char uart_getc(void) {
	loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
	return UDR0;
}

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.