REKLAMA

czujnik.c

Czujnik odległości HC-SR04, LED i Atmega32, język C

Serdecznie dziękuję za pomoc - aktualnie udało mi się opanować czujnik w taki sposób, że oscyloskop pokazuje jego prawidłowe działanie na pinach echo i trigger, a zakomentowana funkcja na dole powoduje zaświecenie lampki na - powiedzmy - 50% jej mocy. Próbuję dojść do tego, jak połączyć działanie funkcji PWM wraz z funkcją od Timer0, ponieważ w obu pojawiaja się rejestr TCCR0 i wydaje mi się, że to jest przyczyną braku reakcji LED na ruch. Jak sobie z tym poradzić?


Pobierz plik - link do postu

// PO£¥CZENIA
// TRIGGER - & gt; PD0
// ECHO - & gt; INT1 PD2
// LED - & gt; PD5 (OC1A)

#define F_CPU 8000000UL // Zegar 8MHz

#include & lt; avr/io.h & gt;
#include & lt; avr/interrupt.h & gt;
#include & lt; util/delay.h & gt;

// LED - zmiana na PD5 po konsultacji z Panem Bujnowskim
#define LED_PIN (1 & lt; & lt; PD5)
#define LED_ON PORTD |= LED_PIN
#define LED_OFF PORTD & = ~LED_PIN

void Wyslij_sygnal(void);
void wlacz_przerwania (void);
void wlacz_timer0 (void);

unsigned char praca;
unsigned char rising_edge;
uint16_t czas_pomiaru;
int distance_cm;
uint8_t error;

// przerwanie timera
ISR (TIMER0_OVF_vect)
{
if(rising_edge==1) // czy pojawi³o siê echo?
{
czas_pomiaru++;
/*Czy nie przekracza zakresu?*/
if(czas_pomiaru & gt; 91)
{
praca = 0;
rising_edge = 0;
error = 1;
}
}
}

ISR (INT1_vect)
{
if(praca==1) // echo - stan wysoki, start timera
{
if(rising_edge==0)
{
rising_edge=1;
TCNT0 = 0;
czas_pomiaru = 0;
}
else // echo - stan niski, przeliczanie otrzymanej wartoœci na cm
{
rising_edge = 0;
distance_cm = (czas_pomiaru*256 + TCNT0)/58;
praca = 0;
}
}
}

// timer - w³¹czenie

void wlacz_timer0()
{
TCCR0 |= (1 & lt; & lt; CS00); // Bez skalowania - tutaj i w pwm pojawia siê TCCR0, jak to rozwi¹zaæ?: & lt;
TCNT0 = 0; // Zerowanie wartoœci
TIMSK |= (1 & lt; & lt; TOIE0); // Przerwania aktywne
}

// aktywacja triggera na pinie D0

void Wyslij_sygnal()
{
if(praca ==0 ) // Czy timer zakoñczy³ swoj¹ pracê?
{
_delay_ms(50); // Restart HC-SR04
PORTD & =~ (1 & lt; & lt; PIND0);
_delay_us(1);
PORTD |= (1 & lt; & lt; PIND0); // Wys³anie impulsu 10ms na trigger
_delay_us(10);
PORTD & =~ (1 & lt; & lt; PIND0);
praca = 1; // gotowoϾ
error = 0; // test b³êdu
}
}

void wlacz_przerwania()
{
MCUCR |= (1 & lt; & lt; ISC10); // wartoϾ logiczna na INT1 (PD3)
GICR |= (1 & lt; & lt; INT1); // aktywowanie INT1
}



void initPWM(unsigned char value)
{
TCCR0 = 0b01101101; // timer 0 jest u¿ywany wczeœniej, nie wiem czy ta funkcja zadziala poprawnie..
OCR0 = value;
}



int main(void)
{
wlacz_przerwania();
wlacz_timer0();
DDRD & =~ (1 & lt; & lt; PIND3); // INT1
DDRD |= (1 & lt; & lt; PIND0); // TRIGGER
sei(); // w³¹czenie przerwañ globalnych

// pwm
unsigned char value = 1;
unsigned char przelicznik = 1;
unsigned char procent = 1;
char liczba = 1;
DDRD |= LED_PIN; //wyjœcie pw na leda
while(1) {
_delay_ms(1);
initPWM(value);
value+=liczba;
if ((value & gt; 254 || value & lt; 1) || ( praca== 0))
{
liczba*=-1;
// tutaj zachodzi przeliczanie wartoœci odleg³oœci na 'value'
procent = distance_cm / 400;
przelicznik = 1 - procent;
value = przelicznik * value;
}
Wyslij_sygnal();
// return 0;
}


/*

while(1)
{
// ta czesc dziala bez initPWM;
if ((praca == 0) & & (distance_cm & lt; 10)) // jak uzaleznic zmienna distance bez u¿ywania pwm lub z u¿yciem??
{
LED_ON;
_delay_ms(500);
}
else
{
LED_OFF;
}
Wyslij_sygnal(); //Restart sygna³u z triggera
}
*/
}