C Silnik krokowy rozbudowa kodu wskazanie idei.

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

C Silnik krokowy rozbudowa kodu wskazanie idei.

Post autor: mictronic » 28 maja 2013, 20:17

Witam, staram się zrobić obsługę 4 silników krokowych bardzo małej mocy, wykorzystuje do tego gołe piny mikrokontrolera przez co program rozbudowuje się do ścisłe określonych stanów logicznych na portach. W skrócie wykorzystuje tranzystory wyjściowe w AVR jak mostek H z użyciem stanu Hi-Z.

Udało mi się z powodzeniem uruchomić pierwszy silnik niestety dochodzę do momentu gdzie obsługa kolejnych silników zmusiłaby mnie do kopiowania kodu i zmian tylko nazw portów, chciałbym aby to odbywało się w locie. Nie wiem jak to wygląda w języku C lub jaka drogę obrać w kierunku optymalizacji. Czytałem o strukturach lecz nie wiem czy one nadają się do operacjach na rejestrach.

Program realizuje odczyt wartości ADC i ustawienie silnika o tą wartość kroków. Sterowanie silnikiem odbywa się w poleceniu SWITCH w przerwaniu TIMER0.

Proszę o propozycje, przedstawiam kod:

Kod: Zaznacz cały

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define SET_BIT(r,x) r|=_BV(x)
#define CLR_BIT(r,x) r&=~_BV(x)
#define TOG_BIT(r,x) r^=_BV(x)
#define dirout DDRD
#define portout PORTD
#define sw1 !(PINB & 1<<PB0)
#define sw2 !(PINB & 1<<PB1)

void adc_init (void);
uint8_t adc_read (uint8_t chanel);

volatile uint8_t zadana=50 ;//wejsciowa wartosc
volatile uint8_t step=0 ;//wyjsciowa
volatile uint8_t pom=0 ;//pomocnicza 

int main(void)
{
	TCCR0 |= (1<<WGM01);				
	TCCR0 |= (1<<CS02)|(1<<CS00);		
	OCR0 = 15;							
	TIMSK |= (1<<OCIE0);			
	sei();
	adc_init();

	while(1)
	{
	zadana=adc_read(1);
	_delay_ms(10);
	}

}


ISR(TIMER0_COMP_vect)
{

	if (zadana>pom) pom++;
	if (zadana<pom) pom--;


	step=pom%4;

	dirout=0;
	portout=0;

	switch(step)
	{

		case 0:
		
		SET_BIT(dirout,0); //1STEP
		SET_BIT(portout,0);
		SET_BIT(dirout,1);
		CLR_BIT(portout,1);

		break;

		case 1:

		SET_BIT(dirout,3); //2STEP
		SET_BIT(portout,3);
		SET_BIT(dirout,2);
		CLR_BIT(portout,2);

		break;

		
		case 2:

		SET_BIT(dirout,1); //3STEP
		SET_BIT(portout,1);
		SET_BIT(dirout,0);
		CLR_BIT(portout,0);

		break;

		case 3:

		SET_BIT(dirout,2); //4STEP
		SET_BIT(portout,2);
		SET_BIT(dirout,3);
		CLR_BIT(portout,3);

		break;

	}

}

void adc_init(void)
{

	ADMUX |=(1<<REFS0)|(1<<ADLAR);
	ADCSRA |=(1<<ADEN)|(1<<ADPS0)|(1<<ADPS1);

}

uint8_t adc_read (uint8_t kanal)
{

	ADMUX|=(ADMUX&0xF8)|kanal;
	ADCSRA|=(1<<ADSC);
	while(ADCSRA & (1<<ADSC));

	return ADCH;

}

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 28 maja 2013, 21:08

Pytana ogólne.
1. Jak chcesz sterować tymi silnikami ? Pełno krokowo, czy pół krokowo ?
2. Czy chcesz mieć wybór między sterowniem pół krokowym a pełno krokowym ?
Odp. na twoje pytanie.
Da się to zrobić stosują 8 elemętową tablicę stałych :) a, cały program będzie śmigał, z szybkością światła ;).

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 29 maja 2013, 7:09

Sterowanie pełnokrokowe mnie usatysfakcjonuje, po kazdym kroku stan pinów musi byc HiZ przykładowo:

1234
1.10ZZ
2.ZZ01
3.01ZZ
4.ZZ10

No jestem ciekawy odpowiedzi.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 29 maja 2013, 18:05

Tablice definiuje sie tak.
bieguny 1234 index tab.
krok 1: 1000___ 0
półkrok1:1100___ 1
krok 2: 0100___ 2
półkrok2:0110___ 3
krok 3: 0010___ 4
półkrok3:0011___ 5
krok 4: 0001___ 6
półkrok4:1001___ 7
I teraz tak jeżeli sterujesz pół krokowo odczytujesz tablicę po kolei, jeżeli pełno krokowo, odczytujesz co drugi element tablicy. Czyli index tablicy obliczasz ?
Nie wiem po co ci te stany Z ? Co chcesz port pozostawiać wiszący w powietrzu ?
Co do ADC odczytuj sobie tylko 8 starszych bitów, 2 młodsze olej, to dużo wygodniejsza metoda odczytu z potencjometru, ponieważ eliminuje w pewnym stopniu zakłócenia, i wahania napięcia.
Kodu w C ci nie napiszą pod AVRa, bo nie znam C na nie zbytnio, siedzę bardziej na procesorach PIC, a tam i samo C nieco inne (bardziej PC-towskie), i porty I/O też. Ale tam Timery mają funkcje sterowania mostkami silników (łącznie 4 tryby podstawowe), więc, większość robi sprzęt ;).
No i jakie to masz silniki dwufazowe ? Bo z twojej tabelki wynika, że zmieniasz kierunek przepływu prądu w cekach ?

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 29 maja 2013, 21:18

Rzeczywiście rozpędziłem sie chyba z tym stanem wysokiej impedancji. Steruje małym silnikiem bipolarnym do którego dorabianie elektroniki i stopnia mocy byloby bezsensowne gdyż wszystko znajduje się juz w procesorze.

Sam pomysł z tablicą wydaje się sensowny, zostawie funkcje switch a do case wrzuce tylko odczyt bezpośrednio na porty. W zwiazku z użyciem 4 silników planuje zajęcie dwóch portów, starsze bity portu na jeden silnik młodsze na drugi, kwestia tylko przesunięcia bitów i wyplucie na port.

Dziękuje za pomoc.

Awatar użytkownika
mictronic
-
Posty: 81
Rejestracja: 04 paź 2006, 19:28
Lokalizacja: Bydgoszcz
Kontakt:

Post autor: mictronic » 30 maja 2013, 19:56

Znowu mam problem tym razem z operacjami bitowymi.
W książce podają taki kod by bezkarnie nadpisać sobie daną cześć bajtu z użyciem maski:

Kod: Zaznacz cały

PORTx = (PORTx & !MASKA) | (pgm_read_byte(&kroki[step]) & MASKA);
Najpierw wgrywam pierwsze młodsze 4 bity dla jednego silnika, a potem muszę najprościej w świecie zrobić to samo i przesunąć o 4 bity... Nie działa mi to w dodatku nie mam konkretnego przykładu bo próbowałem na wiele sposobów. Chodzi oczywiście by zrobic to tak nie uszkadzając pozostałej części bitów. Mogę prosić na nakierowanie w tak prostackiej sprawie?

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 31 maja 2013, 7:08

Przesuwaj sobie to bitowo w ten sposób:
temp = 0
temp = tab dla silnik 2
przsuń temp w prawo o 4
temp = temp or tab, dla silnika 1
port = temp.

Można to spróbować jeszcze zoptymalizować, ale nie mam na to czasu pisząc ten post.

ODPOWIEDZ