Skocz do zawartości

Pseudo tachometr na AVR


Pomocna odpowiedź

Napisano

Hej, mam prośbę, aby ktoś rzucił okiem na kod i zobaczył czy nie walnąłem jakiegoś babola w obliczeniach 🙂 Chcę zrobić taki ala' tachometr, najbardziej zależy mi na pomiarze metrów na minute. Na dzień dzisiejszy wykorzystałem zwykły enkoder inkrementalny blaszkowy, wiem że się nie nadaje do czegoś takiego, ale zasada pomiaru impulsów będzie taka sama, gdy wykorzystam coś innego. Ogólnie wymyśliłem, że w przerwaniu INT zliczam impulsy enkodera, wiedząc że na 1 obr przypada ich 24. Jeśli doliczy do 24 zmieniam stan pinu na przeciwny. W przerwaniu ICP mierze czas pomiędzy tymi impulsami i potem w programie je przeliczam.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#include "LCD/lcd.h"

volatile uint8_t encoder; // impulsy encodera
volatile uint8_t ovf; // licznik przepelnien	
volatile uint16_t result; // pomiar w uS
volatile uint8_t meas; // zmienna pomocnicza
const float obwod = 6.15; // obwod kółka pomiarowego
float metry_na_sekunde;
float metry_na_minute;
float pomiar;
char wynik[20]; 


int main(){
	DDRD |= (1<<PD4); // PIN generujący zbocza dla ICP
	PORTD |= (1<<PD2)|(1<<PD3); // piny INT
	MCUCR |= (1<<ISC00); 
	GICR |= (1<<INT0); // wlaczenie przerwania
	TCCR1B |= (1<<ICES1)|(1<<CS11); // zbocze narastajace i prescaler 8.. 8MHz/8 = 1uS
	TIMSK |= (1<<TICIE1); // zezwolenie na przerwanie
	
	lcd_init();
	sei();
	lcd_locate(0,0);
	lcd_str("TACHOMETR");

	while(1){

		if(meas){
		
		pomiar = (65536 * ovf + result)/1000000.0; // pomiar w sekundach
		metry_na_sekunde = (obwod / 100.0)/pomiar;
		metry_na_minute = metry_na_sekunde * 60;

		sprintf(wynik,"%5.2f", metry_na_minute);
		
		lcd_locate(1,0);
		lcd_str(wynik);
		meas=0;
		}
	}
}

ISR (INT0_vect){
	static uint8_t dir;
	if (!(PIND & (1<<PD2))){
		dir = (PIND & (1<<PD3));
	}else {
		if (dir != (PIND & (1<<PD3))){
			if (dir) {
				encoder++;
				if (encoder > 23){
					PORTD ^= (1<<PD4);
					encoder=0;
				}
			}
			else encoder--;
		}
	}
}
ISR (TIMER1_CAPT_vect){
if (TCCR1B & (1<<ICES1)){ // jesli zbocze narastające
	TCNT1 = 0; // zerujemy licznik TCNT i licznik przepelnien
	ovf=0;
	TIFR |= (1<<TOV1); // zerowanie flagi przerwania ovf
	TIMSK |= (1<<TOIE1); // wlaczenie przerwania od przepelnienia
	TCCR1B ^= (1<<ICES1);// zmiana na zbocze opadajace
}else {
	result = ICR1; // zapisujemy rezultat
	TCCR1B ^= (1<<ICES1);// zmiana na zbocze opadajace
	TIMSK ^= (1<<TOIE1); // wylaczamy przerwanie od przepelnienia
	meas = 1; // pomiar gotowy
}


}
ISR (TIMER1_OVF_vect){
	ovf++; // zwiekszamy licznik przepełnień
}

Najbardziej mi chodzi o część z przeliczeniami, bo się trochę zakręciłem i zastanawiam się czy jakieś tam głupoty nie walnąłem, a nie mam w tym momencie do czego porównać wyników 🙂

hah nic nie zrobi, prócz zliczania impulsów enkodera w tył. Na razie oprogramowanie jest ułomne, działa w jedną stronę. Na razie podstawą dla mnie sa obliczenia, czy są poprawne 😛  

Nie mam na czym sprawdzić, ale 65536 w 16-bitowej arytmetyce to takie nie bardzo... jeśli już zdecydowałeś się na floaty to 65536.0 raczej.

  • Lubię! 1
(edytowany)

Łatwiej by było podać impulsy z enkodera na wejście zliczające któregoś z timerów. Oczywiście należy też uwzględnić uwagi @ethanaka. Z jaką częstotliwością mają się obywać pomiary? 

Edytowano przez _LM_
  • Lubię! 1

@ethanak masz racje, ale zmiana ta nie wpłyneła na wyświetlany wynik. (Testuje wkretarką) 😄 O częstotliwości pomiaru nie myślałem, docelowo mam na myśli podręczne urządzenie do pomiaru, kiedy jest potrzeba zmierzyć prędkość jakiegoś medium. Docelowo zastanawiam się nad tym jak podejść do wykonania takiego tachometru, czy użyć jakiś enkoder optyczny lub inne rozwiązanie by to było w miare poręczne i proste do zrealizowania. Sposobów na pomiar jest dużo, foto diody, czujniki halla itp. 

Jeśli to się kręci tylko w jedną stronę lub potrzebna jest prędkość niezależnie od kierunku, enkoder kwadraturowy nie jest tu potrzebny. Wystarczy podanie impulsu z np. hallotronu (tak robiłem prędkościomierze do motocykla) na wejście timera zgodnie z tym co pisał @_LM_). Program się nieco upraszcza...

  • Pomogłeś! 1

Tak, z czujnikiem halla by się to bardzo uprościło bo bym po prostu na cały obrót miał 1-2 impulsy z czujnika, niezależnie w którą stronę kręci się kółko. Tylko średnio mogę sobię wyobrazić konstrukcje tego. 

Zobacz jak są zrobione enkodery Pololu. W Botlandzie możesz dostać same dyski z magnesami. Różnica taka, że dajesz jeden hallotron zamiast dwóch.

 

  • Lubię! 1

Im więcej impulsów na obrót tym większa rozdzielczość pomiaru. Dla urządzenia uniwersalnego należałoby mieć możliwość zmiany czasu próbkowania. Tak żeby móc mierzyć zarówno wolne jak i szybkie obiekty. 

  • Lubię! 1
1 minutę temu, Krawi92 napisał:

Gdybym miał 4 impulsy na obrót byłoby to optymalne ?

A nie wiem 😉 trzeba wziąć kalkulator i policzyć. Zakładając że nie będzie poślizgu i "cofki" trzeba by oszacować i określić dokładność pomiaru jaka jest wymagana? Cztery impulsy na obrót.... To ile obrotów zrobi enkoder zależy od tego na jakim kole będzie zamocowany 

Dyski enkoderów mają z reguły 5 lub 7 magnesów więc sobie przelicz jaka będzie dokładność.

@_LM_ dla szybkich obrotów mierzysz ilośc impulsów w jednostce czasu, dla wolnych czas między kolejnymi impulsami.

  • Lubię! 1

Ech...

Pamiętaj, że im więcej impulsów dostaniesz tym dokładniejszy jest wynik. Szybkie to takie, gdzie dostajesz wystarczającą ilość impulsów w jednostce czasu, aby móc obliczyć z jakąś poludzką dokładnością wynik. Wolne to takie, co nie są w tym przypadku szybkie.

A wartości sobie przelicz bo to zależy od jednostki czasu i ilości impulsów na obrót.

  • Pomogłeś! 1

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