Skocz do zawartości

Bardzo dziwny problem z przyciskiem


Pomocna odpowiedź

Napisano

Witam, mam coś czego kompletnie nie rozumiem, otóż mam 2 przyciski i silnik podłączony do mostka l293d, chcę aby po naciśnięciu drugiego przycisku kręcił się silnik, ale silnik w ogóle nie reaguje na przycisk, kręci się sam bez naciścięcia. Ale co jest dziwne: w tym samym kodzie, tylko z innym przyciskiem tylko na innym pinie normalnie działa! I o co tu chodzi? Oto kod z pierwszym przyciskiem, działa prawidłowo:

#define F_CPU 1000000L 
#include <avr/io.h> 
#include <util/delay.h>


void pwm_init()
{

TCCR1A |= (1<<WGM10) | (1<<COM1A1) | (1<<COM1B1); // timer 1
TCCR1B |= (1<<WGM12) | (1<<CS10);

DDRB |= (1<<PB1) | (1<<PB2); // output pwm

}

void init()
{

DDRD |= (1<<PD0) | (1<<PD1); // motor 1
PORTD |= (1<<PD1) | (1<<PD0);

PORTD |= (1<<PD3);// switch 1
DDRD |= (1<<PD3);
}

int main(void)
{

pwm_init();

init();

while(1)
{

if(PIND & 0x08)
{

PORTD |= (1<<PD0);
PORTD &= ~(1<<PD1);
OCR1A = 190;
}

}
}

Program z innym przyciskiem, nie działa:

#define F_CPU 1000000L 
#include <avr/io.h> 
#include <util/delay.h>


void pwm_init()
{

TCCR1A |= (1<<WGM10) | (1<<COM1A1) | (1<<COM1B1); // timer 1
TCCR1B |= (1<<WGM12) | (1<<CS10);

DDRB |= (1<<PB1) | (1<<PB2); // output pwm

}

void init()
{

DDRD |= (1<<PD0) | (1<<PD1); // motor 1
PORTD |= (1<<PD1) | (1<<PD0);

PORTB |= (1<<PB6);// switch 2
DDRB |= (1<<PB6);
}

int main(void)
{

pwm_init();

init();

while(1)
{

if(PINB & 0x40)
{

PORTD |= (1<<PD0);
PORTD &= ~(1<<PD1);
OCR1A = 190;
}

}
}

Jak widać zmieniam tutaj tylko konfiguracje przycisku, więc na moje oko wszystko powinno działać tak samo, a w drugim przypadku jak pisałem wcześniej silnik kręci się sam nie reagując na przycisk. Proszę o wyjaśnienie co jest nie w porządku.

Pozdrawiam.

Może przez przypadek na stałe zwarłeś PB6 z masą. To jest na płytce stykowej czy na własnoręcznie wytrawionej płytce. Jeżeli na własnej, to pokaż spód płytki, może coś to pomoże.

[ Dodano: 18-11-2012, 20:40 ]

EDIT: Mógłbyś dać więcej komentarzy, oraz jakieś makrodefinicje, by poprawić czytelność kodu.

[ Dodano: 18-11-2012, 20:44 ]

EDIT: I jeszcze jedno. Złap multimetrem oba piny switcha, i zobacz, czy nie ma tam zwarcia.

Układ mam na płytce stykowej. Chciał bym aby po naciśnięciu pierwszego przycisku zaczął chodzić silnik o wypełnieniu pwm 170, a z każdym naciśnięciem drugiego przycisku pwm zwiększał by się o 20, jednak działa to w ten sposób że po naciśnięciu pierwszego, silnik chodzi przy pwm 170, ale na drugi przycisk już nie reaguje, albo przy naciśnięciu drugiego przycisku chodzi z pwm=190. Co zmienić w kodzie żeby działało poprawnie?

#define F_CPU 1000000L 
#include <avr/io.h> 
#include <util/delay.h>


void pwm_init()
{

TCCR1A |= (1<<WGM10) | (1<<COM1A1); // timer 1
TCCR1B |= (1<<WGM12) | (1<<CS10);

DDRB |= (1<<PB1); // output pwm

}

void init()
{
DDRD |= (1<<PD0)|(1<<PD1); // motor 1
PORTD |= (1<<PD1) | (1<<PD0);

PORTD |= (1<<PB3);//przycisk 1
PORTB |= (1<<PB6);// przycisk 2
DDRD &= ~(1<<PD3);// przycisk 1 z podciągnięciem do Vcc
DDRB &= ~(1<<PB6);// przycisk 2 z podciągnięciem do Vcc
}

int main(void)
{

pwm_init();

init();
int i;

uint8_t predkosc;

predkosc = 170;

while(1)
{
for(i=0;i<5;i++);
{

if(!(PIND & 0x08)) // jesli pierwszy przycisk
{

PORTD |= (1<<PD0);
PORTD &= ~(1<<PD1);
OCR1A = predkosc;

}
else if(!(PINB & 0x40)) // jesli drugi przycisk
{
 if(predkosc >= 170)
  {
    PORTD |= (1<<PD0);
	PORTD &= ~(1<<PD1);
	predkosc += 20;

  }

}
}
}
}

Proszę o pomoc

Zrób wcięcia w kodzie, będzie czytelniejszy.

Dlaczego nie zrobiłeś makrodefinicji OCR1A? Wtedy byłoby łatwiej i czytelniej.

"OCR1A = predkosc; " no ale to chyba się dzieje tylko w tym miejscu w kodzie.

A zobacz co się stanie jeżeli zamiast gwiazdek wstawisz '' OCR1A = predkosc ; ''

if(predkosc >= 170)

{

PORTD |= (1<

PORTD &= ~(1<

predkosc += 20;

*******

}

Ok, wykombinowałem coś takiego:

#define F_CPU 1000000L 
#include <avr/io.h> 
#include <util/delay.h>


void pwm_init()
{

TCCR1A |= (1<<WGM10) | (1<<COM1A1); // timer 1
TCCR1B |= (1<<WGM12) | (1<<CS10);

DDRB |= (1<<PB1) | (1<<PB2); // output pwm

}

void init()
{
DDRD |= (1<<PD0)|(1<<PD1); // motor 1
PORTD |= (1<<PD1) | (1<<PD0);

PORTD |= (1<<PB3);//przycisk 1
PORTB |= (1<<PB6);// przycisk 2
DDRD &= ~(1<<PD3);// przycisk 1 z podciągnięciem do Vcc
DDRB &= ~(1<<PB6);// przycisk 2 z podciągnięciem do Vcc
}

int main(void)
{

pwm_init();

init();

uint8_t predkosc;

predkosc = 170;

while(1)
{

if(!(PIND & 0x08)) // jesli pierwszy przycisk
{

PORTD |= (1<<PD0);
PORTD &= ~(1<<PD1);
OCR1A = predkosc;


if(!(PINB & 0x40)) // jesli drugi przycisk
{
 if(predkosc = 170)
  {
    PORTD |= (1<<PD0);
	PORTD &= ~(1<<PD1);
	predkosc += 20;
	OCR1A = predkosc;

  }

}
}
}
}

Działa prawie dobrze, z początku drugi przycisk nie działa, trzeba wcisnąć pierwszy, kręci się nie z pełną mocą, a po naciśnięciu drugiego przycisku kręci się szybciej, tylko że działa to tylko raz:) a ja chciał bym żeby za każdym razem nabierał prędkości, co w tym wypadku należało by zmienić? Myślę że jakaś lekka poprawka i będzie ok.

if(predkosc = 170)

{

PORTD |= (1<

PORTD &= ~(1<

predkosc += 20;

OCR1A = predkosc;

}

Za drugim razem prędkość masz już równą 190 a nie 170, tak?

Więc warunek nie spełniony, i instrukcje wewnątrz " if(predkosc = 170) " nie są wykonywane

Teraz przyjżałem się jeszcze raz. Zrobiłeś podstawowy błąd.

if(predkosc = 170)

Ty nie PORÓWNUJESZ, tylko nadajesz zmiennej prędkość wartość 170.

(Aby porównać powinieneś dać znak ==)

W ogóle potrzebujesz ten warunek: if(predkosc == 170) ?

Powtarzam, zrób wcięcia w kodzie, będzie O WIELE CZYTELNIEJ.

Uczę się c++ jedynie przez internet i serdeczną pomoc użytkowników forum, także obawiam się że podstawowe problemy nękać mnie będą jeszcze przez długi czas:) ale cieszę się że jest jakiś postęp. No cóż, popróbuje z tym jutro. Dziękuję za odpowiedź, napiszę jeśli coś będzie nie tak.

Ok, działa już zwiększanie prędkości podczas naciśnięcia przycisku drugiego, jednak chciałbym aby przycisk 3 z kolei zmniejszał prędkość, napisałem taki kod:

#define F_CPU 1000000L 
#include <avr/io.h> 
#include <util/delay.h>

#define silnik_lewo PORT

#define _BV(bit) (1 << (bit))


void pwm_init()
{

TCCR1A |= (1<<WGM10) | (1<<COM1A1); // timer 1
TCCR1B |= (1<<WGM12) | (1<<CS10);

DDRB |= _BV(1) | _BV(2); // output pwm

}

void init()
{
DDRD |= _BV(0)| _BV(1); // motor 1
PORTD |= _BV(1) | _BV(0);

PORTD |= _BV(3);//przycisk 1
PORTB |= _BV(6);// przycisk 2
PORTD |= _BV(7);//przycisk 3
DDRD &= ~_BV(3);// przycisk 1 z podciągnięciem do Vcc
DDRB &= ~_BV(6);// przycisk 2 z podciągnięciem do Vcc
DDRD &= ~_BV(7);// przycisk 3 z podciągnięciem do Vcc
}

int main(void)
{

pwm_init();

init();

uint8_t predkosc;

predkosc = 170;

while(1)
{
if(!(PIND & 0x08)) // jesli pierwszy przycisk
{
	PORTD |= _BV(0);
	PORTD &= ~_BV(1);
	OCR1A = predkosc;
	_delay_ms(80);



	if(!(PINB & 0x40)) // jesli drugi przycisk
	{
		predkosc += 10;
		if(predkosc>240)
		predkosc = 170;
		_delay_ms(80);



	if(!(PIND & 80))
	{
		predkosc -= 10;
		_delay_ms(80);
	}

}
}
}
}

Wzorowałem się na tej stronie: http://mikrokontrolery.blogspot.com/2011/02/if-warunkowa-instrukcja-sterujaca.html

Tylko właśnie obawiam się że jeśli warunek 2 mam spełniony, to warunku 3 program nie bierze pod uwagę, próbowałem różnymi sposobami ale nie wychodzi. Proszę o wyjaśnienie co tu jest nie tak.

Pozdrawiam.

Z tego co widzę, to sprawdzasz 3 warunek tylko wtedy kiedy drugi jest spełniony, a drugi warunek sprawdzasz tylko wtedy kiedy pierwszy jest spełniony.

Chyba nie taka była Twoja intencja;) Przyprzyj się dokładnie gdzie otwierasz a gdzie zamykasz klamry 'bloków' if.

#define F_CPU 1000000L 
#include <avr/io.h> 
#include <util/delay.h> 

#define silnik_lewo PORT 

#define _BV(bit) (1 << (bit)) 


void pwm_init() 
{ 

TCCR1A |= (1<<WGM10) | (1<<COM1A1); // timer 1 
TCCR1B |= (1<<WGM12) | (1<<CS10); 

DDRB |= _BV(1) | _BV(2); // output pwm 

} 

void init() 
{ 
DDRD |= _BV(0)| _BV(1); // motor 1 
PORTD |= _BV(1) | _BV(0); 

PORTD |= _BV(3);//przycisk 1 
PORTB |= _BV(6);// przycisk 2 
PORTD |= _BV(7);//przycisk 3 
DDRD &= ~_BV(3);// przycisk 1 z podciągnięciem do Vcc 
DDRB &= ~_BV(6);// przycisk 2 z podciągnięciem do Vcc 
DDRD &= ~_BV(7);// przycisk 3 z podciągnięciem do Vcc 
} 

int main(void) 
{ 

pwm_init(); 

init(); 

uint8_t predkosc; 

predkosc = 170; 

while(1) 
{ 
   if(!(PIND & 0x08)) // jesli pierwszy przycisk 
   { //klamra otwiera 1 ifa
       PORTD |= _BV(0); 
       PORTD &= ~_BV(1); 
       OCR1A = predkosc; 
       _delay_ms(80); 
 }//zamyka 1 ifa      

 if(!(PINB & 0x40)) // jesli drugi przycisk 
       { //otwiera drugiego ifa
           predkosc += 10; 
           if(predkosc>240) 
           predkosc = 170; 
           _delay_ms(80); 
        }//zamyka drugiego ifa


       if(!(PIND & 80)) 
       { //otwiera 3 ifa
           predkosc -= 10; 
           _delay_ms(80); 
       } //zamyka 3 ifa

} //zamyka while
} //zamyka main

Teraz program sprawdzi Ci w pętli głównej wszystkie trzy warunki zaczynając od pierwszego, zupełnie nie zależnie.

Już próbowałem tak wcześniej, ale niestety nie reaguje na 3 przycisk, chociaż on działa bo sprawdzałem. Ten program zatrzymuje się przy drugim if'ie. Spróbowałem z break;, w ten sposób:

if(predkosc>240) break;

teraz silnik się rozpędza do wysokich obrotów i nie reaguje na nic, chyba wychodzi z pętli także to zły pomysł jest.

[ Dodano: 24-11-2012, 16:07 ]

Tutaj np. idealnie działa podobny program:

http://mnowator.pl/tag/sterowanie-jasnoscia-diody-led-przez-pwm/ ale jakoś nie mogę dojść do tego, może ta funkcja return 0 coś zmieni?

Albo spróbować coś z else if...

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...