Ovládanie vyklápacích svetiel: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
|||
Riadok 18: | Riadok 18: | ||
== Analýza a opis riešenia == | == 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 | |||
[[Súbor:Rele_doska.jpg|400px|thumb|center|Relé doska]] | |||
[[Súbor: | 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 === | ||
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:''' | |||
#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=" | <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" | |||
#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(); | |||
} | |||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
<tab name=" | <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 | |||
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; | |||
} | |||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
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

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

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:

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:
- 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>
#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.

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