Enkoder w LinuxCNC, toczenie gwintu, parametry

Dyskusje dotyczące działania obsługi programu LinuxCNC

Autor tematu
drzasiek90
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 9
Posty: 2329
Rejestracja: 25 kwie 2016, 11:58
Lokalizacja: Jodlowa
Kontakt:

Re: Enkoder w LinuxCNC, toczenie gwintu, parametry

#51

Post napisał: drzasiek90 » 13 maja 2023, 20:54

tuxcnc pisze:
13 maja 2023, 15:26
Ale niech Ci będzie, na przyszłość będę pisał "kresek na obrót", żebyś się nie przypieprzał do jednej literki w zdaniu, które jest absolutnie jednoznaczne...
Zupełnie nie rozumiem twojego podejścia.
Zdementowałem bzdurę, którą napisałeś i tyle. Wydaje mi się, że kulturalnie.
U ciebie nie było literówki, u mnie nie było przypieprzania.
A jednoznaczne jest tylko w tedy, gdy jest zgodne z prawdą, a nie tak jak ty błędnie sobie zakodowałeś w głowie.
Przecież sam, jak twierdzisz, "stoisz na straży" konkretnych wypowiedzi i dementowania bzdur na forum publicznym, ponieważ ktoś wejdzie, przeczyta, że 100 cpr oznacza 100 kresek na tarczy i zostanie wprowadzony w błąd.
tuxcnc pisze:
13 maja 2023, 15:26
Jeśli będziesz liczył co sekundę, to niczego nie polepszysz...
Ale jeśli będziesz miał zauważyć znak drogowy, ale będziesz sprawdzał co minutę, to jest duża szansa, że go przegapisz.
Jeśli gwintowanie rozpoczyna się od indexu, to policzmy przykładową sytuację:
Obroty 800rpm.
Jeśli sygnał index pojawił się 1 ns po wywołaniu wątku, to gdy wątek wywoływany jest co 1 ms to w zaokrągleniu za 1 ms dopiero zostanie to zdekodowane i rozpocznie się cykl.
Dla 800 rpm daje to 0,0133 obrotu, a więc 4,8 stopnia.
Jeśli będzie się zdarzać sytuacja, że index raz się pojawi tuż przed wywołaniem wątku a innym razem tuż po wywołaniu wątku, będziemy mieli około 4,8 stopnia różnicy w przejazdach, a więc gwint się rozjedzie.
tuxcnc pisze:
13 maja 2023, 15:26
Tak sobie na spokojnie to przemyślałem i doszedłem do wniosku, że tam też piszą głupoty.
Raczej prawda jest taka, że błędem jest użycie pojęcia cpr do enkodera, bo "c" jest faktycznie od "counts", ale przecież enkoder niczego nie liczy, on tylko wystawia stany na wyjściach...
A pisanie o "elektronicznym mnożeniu przez cztery", to już kompletny debilizm.
Ach ta duma. Walcz z nią :)
Wszystko jest logiczne, CPR - counts per revolution, PPR - pulses per revolution.

Dodane 2 godziny 37 minuty 37 sekundy:
Tak jeszcze w ramach ciekawostki.
Kupiłem jakiś czas temu u chińczyka enkoder 38S6G5-B-G24N 50ppr (chińczyk podaje 50 P/R).
Chciałem 25 PPR, tak aby mieć te wcześniej tutaj wspomniane 100cpr które rzekomo miało być max dla linuxcnc - chciałem testować max, no ale 50 PPR to było najmniej co znalazłem.
No ale to było zanim jeszcze się dowiedziałem, że index jest niezbędny, więc kupiłem z wyjściami AB, bez indeksu.
Zrobiłem więc sobie w międzyczasie enkoder 100cpr na transoptorach (w sumie znalazłem fajne bardzo małe więc podam model, gdyby ktoś był zainteresowany - ITR20403) noi działa.
Chciałem sobie zrobić enkoder na enkoderze magnetycznym AMS (mam kilka sztuk, kiedyś wysyłali sample, nie wiem czy nadal wysyłają) + uc do konfigurowania ale mi się nie chciało, więc zostało na transoptorach szczelinowych.
Enkoder na transoptorach szczelinowych nie jest idealny, z tego względu, że okienko transoptora ma pewną szerokość, stąd ciężko uzyskać przebiegi o wypełnieniu 50% i idealne przesunięcie fazowe 90 pomiędzy AB. Jeśli przebiegi nie są "książkowe", to maksymalna prędkość obrotowa jaką da się zmierzyć przy danej częstotliwości próbkowania również spada.
Dlatego zdecydowanie lepszym rozwiązaniem jest użycie układu scalonego (np. enkoder magnetyczny z odpowiednim wyjściem lub inny układ, który te sygnały wygeneruje).
Dziś z ciekawości rozkręciłem enkoder od chińczyka, odnalazłem całkiem ciekawą płytkę w środku.
PCB ma wyprowadzony również sygnał Z, ale chińczyk nie dolutował kabelka.
Na PCB siedzi układ MagnTek MT6701 - enkoder magnetyczny, który ma między innymi wyjścia ABZ a rozdzielczość jest programowana w zakresie 1 - 1024 Pulses per Revolution (PPR).
Całkiem fajny scalak.




tristar0
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 19
Posty: 3052
Rejestracja: 21 sty 2020, 17:48
Lokalizacja: Toruń miasto Tadeusza R

Re: Enkoder w LinuxCNC, toczenie gwintu, parametry

#52

Post napisał: tristar0 » 14 maja 2023, 10:19

drzasiek90 pisze:Dziś z ciekawości rozkręciłem enkoder od chińczyka, odnalazłem całkiem ciekawą płytkę w środku.
PCB ma wyprowadzony również sygnał Z, ale chińczyk nie dolutował kabelka.
taką ciekawostkę też odkryłem jakiś czas temu w tych tanich enkoderach z PRC ,chyba robią masówkę pcb a potem w zależności od zamówienia dokładają 4 lub 5 żyłowy kabelek.
Mam wyrypane na wszelkiej maści proroków ,mędrców i wszystkich którzy stawiają się ponad innymi ,i tak ich zjedzą robaki


Autor tematu
drzasiek90
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 9
Posty: 2329
Rejestracja: 25 kwie 2016, 11:58
Lokalizacja: Jodlowa
Kontakt:

Re: Enkoder w LinuxCNC, toczenie gwintu, parametry

#53

Post napisał: drzasiek90 » 22 maja 2023, 10:38

Załączam prosty kod dla stm32f103 na zmianę rozdzielczości do enkodera MT6701 - można go użyć do zmiany innych parametrów.
Nie wiem czy ktoś będzie potrzebował, ale wrzucam, na wypadek, gdyby mi było jeszcze kiedyś potrzebne.

Kod: Zaznacz cały



/* Includes */
#include <stddef.h>
#include "stm32f10x.h"

#define I2C_SLAVE_ADDR 0x06		//adres urządzenia slave
#define I2C_REG_ADDR 0x31		//rejestr do zapisu
#define I2C_DATA 199			//Dana I2C - w tym przypadku rozdzielczość enkodera

static uint8_t  fac_us = 0;

void delay_init( uint8_t SYSCLK )
{
	SysTick->CTRL &= 0xFFFFFFFB;
	fac_us = SYSCLK / 8;
}

void delay_ms( uint16_t ms )
{
	while( ms-- )
	     delay_us( 999 );
}

void delay_us( uint32_t us )
{
	uint32_t temp;
	SysTick->LOAD = us * fac_us;
	SysTick->VAL = 0x00;
	SysTick->CTRL = 0x01;
	do
	{
		temp = SysTick->CTRL;
	}
	while( temp & 0x01 &&!( temp & ( 1 << 16 )));
	SysTick->CTRL = 0x00;
	SysTick->VAL = 0x00;
}

volatile void delay_ticks(volatile uint32_t t)
{
	while( (volatile)t--);
}

void led_init()
{
	RCC->APB2ENR|= RCC_APB2ENR_IOPCEN;
	GPIOB->CRH &=~ (GPIO_CRH_MODE13 | GPIO_CRH_CNF13);
	GPIOC->CRH |= GPIO_CRH_MODE13_0;//Output mode, max speed 10 MHz
}

void led_OFF()
{
	GPIOC->BSRR = GPIO_BSRR_BS13;
}

void led_ON()
{
	GPIOC->BSRR = GPIO_BSRR_BR13;
}

void led_TGL()
{
	GPIOC->ODR ^= GPIO_ODR_ODR13;
}

void I2C_init(void)
{
    // Włącz taktowanie dla I2C
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;

    // Konfiguruj piny jako alternatywne funkcje open-drain
	GPIOB->CRL &= ~(GPIO_CRL_MODE6 | GPIO_CRL_CNF6 | GPIO_CRL_MODE7 | GPIO_CRL_CNF7);
	GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7;

	delay_ms(500);

	// Konfiguruj parametry I2C1
	I2C1->CR1 &= ~I2C_CR1_PE; // Wyłącz I2C1 przed konfiguracją
	I2C1->CR1 |= I2C_CR1_SWRST; // Zresetuj I2C1
	delay_ms(1);
	I2C1->CR1 &= ~I2C_CR1_SWRST;

	// Skonfiguruj prędkość I2C1
	I2C1->CR2 &= ~I2C_CR2_FREQ;
	I2C1->CR2 |= 1; // Ustaw czestotliwość APB1 na 36 MHz (odpowiednie dla większości konfiguracji mikrokontrolera)
	// Wyłącz przerwania I2C
	I2C1->CR2 &= ~I2C_CR2_ITEVTEN;

	I2C1->CCR &= ~I2C_CCR_CCR;
	I2C1->CCR |= 180; // Ustaw CCR na wartość zapewniającą prędkość 100 kHz

	I2C1->TRISE = 37; // Ustaw TRISE na wartość zapewniającą odpowiednie opóźnienie dla prędkości 100 kHz

	// Włącz I2C1
	I2C1->CR1 |= I2C_CR1_PE;
}

void I2C_SendByte(uint8_t slave_addr, uint8_t reg_addr, uint8_t data)
{
	// Czekaj, aż I2C1 będzie gotowy do transmisji
	while ((I2C1->SR2 & I2C_SR2_BUSY) != 0);

	// Generuj warunek START
	I2C1->CR1 |= I2C_CR1_START;

	// Czekaj na zakończenie warunku START
	while ((I2C1->SR1 & I2C_SR1_SB) == 0);

    // Wysłanie adresu slave (zapis)
    I2C1->DR = (slave_addr << 1) & 0xFE;
    while (!(I2C1->SR1 & I2C_SR1_ADDR)); // Czekaj na potwierdzenie adresu

    // Odczytanie SR2
    (void)I2C1->SR2;

    // Wysłanie adresu rejestru
    I2C1->DR = reg_addr;
    while (!(I2C1->SR1 & I2C_SR1_TXE)); // Czekaj na pusty bufor

    // Wysłanie danych
    I2C1->DR = data;
    while (!(I2C1->SR1 & I2C_SR1_TXE)); // Czekaj na pusty bufor

    // Wysłanie stopu
    I2C1->CR1 |= I2C_CR1_STOP;
}

uint8_t I2C_ReadByte(uint8_t slave_addr, uint8_t reg_addr)
{
    uint8_t receivedData;

    // Czekaj, aż I2C1 będzie gotowy do transmisji
    while ((I2C1->SR2 & I2C_SR2_BUSY) != 0);

    // Generuj warunek START
    I2C1->CR1 |= I2C_CR1_START;

    // Czekaj na zakończenie warunku START
    while ((I2C1->SR1 & I2C_SR1_SB) == 0);

    // Wysłanie adresu slave (zapis)
    I2C1->DR = (slave_addr << 1) & 0xFE;
    while (!(I2C1->SR1 & I2C_SR1_ADDR)); // Czekaj na potwierdzenie adresu

    // Odczytanie SR2
    (void)I2C1->SR2;

    // Wysłanie adresu rejestru
    I2C1->DR = reg_addr;
    while (!(I2C1->SR1 & I2C_SR1_TXE));
    // Czekaj na pusty bufor

    // Generuj warunek RESTART
    I2C1->CR1 |= I2C_CR1_START;

    // Czekaj na zakończenie warunku RESTART
    while ((I2C1->SR1 & I2C_SR1_SB) == 0);

    // Wysłanie adresu slave (odczyt)
    I2C1->DR = (slave_addr << 1) | 0x01; // Ustaw bit kierunku na odczyt
    while (!(I2C1->SR1 & I2C_SR1_ADDR)); // Czekaj na potwierdzenie adresu

    // Odczytanie SR2
    (void)I2C1->SR2;

    // Wyłącz przerwania I2C
    I2C1->CR2 &= ~I2C_CR2_ITEVTEN;

    // Włącz odczyt ACK
    I2C1->CR1 &= ~I2C_CR1_ACK;

    // Generuj warunek STOP
    I2C1->CR1 |= I2C_CR1_STOP;

    // Czekaj na odczyt bajtu danych
    while (!(I2C1->SR1 & I2C_SR1_RXNE));

    // Odczytaj otrzymany bajt danych
    receivedData = I2C1->DR;

    return receivedData;
}

int main(void)
{
	delay_init(72);
	led_init();
	led_ON();
	delay_ms(200);
	led_OFF();
	I2C_init();

	delay_ms(50);
	// Wysłanie danych
	I2C_SendByte(I2C_SLAVE_ADDR, I2C_REG_ADDR, I2C_DATA);//Programowanie rejestru
	I2C_SendByte(I2C_SLAVE_ADDR, 0x09, 0xb3);//Klucz programowania
	I2C_SendByte(I2C_SLAVE_ADDR, 0x0A, 0x05);//Komenda programowania
	delay_ms(700);//Odczekanie conajmniej 600 ms na zakończenie operacji
	uint8_t read = I2C_ReadByte(I2C_SLAVE_ADDR, I2C_REG_ADDR);//odczyt zapisanego rejestru

	if(read != I2C_DATA)//porównanie
	{
		while(1)//jeśli nieprawidłowe, to LED mróga
		{
			led_TGL();
			delay_ms(200);
		}
	}

	led_ON();//Led świeci, prawidłowy odczyt

	while (1);
}

Połączenie należy wykonać według schematu z dokumentacji:
Obrazek

Konfiguracja pod płytkę bluepill.
SCL to noga PB6 mikrokontrolera, SDA to noga PB7.
Po poprawnym ustawieniu rejestru, dioda na wyjściu PC13 zaświeci, gdy odczytana wartość nie zgodzi się z zapisaną, dioda będzie mrugać.

Szkoda się bawić w enkodery na transoptorach bo jakość sygnału kwadraturowego z wykonanego enkodera będzie zawsze powodować ograniczenie maksymalnej prędkości.
Ten enkoder kosztuje grosze i naprawdę uważam, że wart jest uwagi.

ODPOWIEDZ Poprzedni tematNastępny temat

Wróć do „LinuxCNC (dawniej EMC2)”