Atmeg32+czujnik przyspieszenia+PWM

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
skoren86
-
Posty: 9
Rejestracja: 27 paź 2010, 16:10
Lokalizacja: Yawoźno

Atmeg32+czujnik przyspieszenia+PWM

Post autor: skoren86 » 27 wrz 2011, 20:37

Witam.

Mam takie pytanie:)

Algorytm:

odczyt z czujnika ---> porownanie z wartościa w tablicy ---> wystawienie odpowiedniego sygnału PWM

Ze wzgledu na to ze jestem poczatkujący w programowaniu, ale nie oporny na wiedze , dlatego tez czy ktoś moglby wrzucic kawalek jakiegos programu w C ktory realizowalby powyzszy schemat i pomoglby mi zrozumiec jak zastosować przerwania, tablice itd ?.

Poczatkowo ustawilem juz przetworniki ADC do ktorych podpiete sa czujniki i wlaczylem przerwania od timera1 gdyz go bede wykorzystywal do PWM.

Pozdrawiam

keruseykaryu

Post autor: keruseykaryu » 28 wrz 2011, 19:53

odczyt z czujnika ---> porownanie z wartościa w tablicy ---> wystawienie odpowiedniego sygnału PWM
Ze wzgledu na to ze jestem poczatkujący w programowaniu, ale nie oporny na wiedze , dlatego tez czy ktoś moglby wrzucic kawalek jakiegos programu w C ktory realizowalby powyzszy schemat i pomoglby mi zrozumiec jak zastosować przerwania, tablice itd ?.
To nie bascom, że to można załatwić dwoma albo trzema instrukcjami. Nic nie wiemy co i jak masz popodłączane. Albo jak to chcesz mieć.
Mogę napisać

Kod: Zaznacz cały

OCR1A = search_table(PWMTABLE, read_g_detector(REAR_DETECTOR));
Tylko co będziesz z tego wiedział?
Poczatkowo ustawilem juz przetworniki ADC do ktorych podpiete sa czujniki i wlaczylem przerwania od timera1 gdyz go bede wykorzystywal do PWM.
Po co ci przerwania z PWMa? Obejdzie się bez.

skoren86
-
Posty: 9
Rejestracja: 27 paź 2010, 16:10
Lokalizacja: Yawoźno

Post autor: skoren86 » 29 wrz 2011, 9:50

A wiec teraz dokladniej:

Podlączenia:

PWM PORTD 4,5
Czujnik PORTA 0,1,2

Beda dwie tablice:
Tablica1
Tablica2

Bede upuszczać pewien obiekt z wysokosci do 0,5m, w tym czasie wartość z czujnika bedzie calkowana aby uzyskac predkość i wartość ta bedzie porownywana z tablicy1 I 2. Gdy odczyty bedzie sie zawieral w tablicy1 ma nie wystepowac sygnał PWM, a gdy w tablicy2 sygnał PWM ma sie pojawic. Sygnał PWM zostaje podawanay na tr MOSFET i tak jest generowany aby wytworzyc prąd wartości od 1 - 5 A

Pozdrawiam

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

Post autor: kayron » 29 wrz 2011, 11:32

A ten czujnik jest jaki 1, 2 ,3 osiowy? Zbyt dużo ogólników. Do czego chcesz wykorzystat ten czujnik ? Nie wiem ABS, ESP w modelu samochodu czy co ?

skoren86
-
Posty: 9
Rejestracja: 27 paź 2010, 16:10
Lokalizacja: Yawoźno

Post autor: skoren86 » 29 wrz 2011, 12:12

czujnik trzyosiowy, jest wykorzystywany podczas tlumienia upadku a dokladniej:

zamontowany jest na stopie robota wraz z elektromagnesami i ciecza magnetoreologiczna. W trakcie upadku wczytuje wattrosci i odpowiednio zamienia je na sygnal PWM, ktory nastepnie wysylany jest do elektromagnesów tworząc odpowienie pola magnetyczne dla Cieczy MR. Jest to moja praca do obrony mam juz calość tylko opowiednio zaprogramowac UK w C dlatego tyle pytan odnosnie wytlumaczenia mi od czego rozpoczac pisanie, dodam ze wyswietlacz LCD, petle opoznien, przyciski sa juz gotowe.


Czujnik MMA734..

skoren86
-
Posty: 9
Rejestracja: 27 paź 2010, 16:10
Lokalizacja: Yawoźno

Post autor: skoren86 » 01 paź 2011, 19:18

Zamieszczam skrypt tego co do chwili obecnej zrobilem. Prosze o spraqwdzenie poprawnosci napiisania przerwania dla ADC.

Kod: Zaznacz cały

//#define F_CPU   16000000
#include "hd.h"
#include<avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>

#define przycisk PINC

#define ELEKTROMAGNES PORTD
#define ELM1 4
#define ELM2 5
#define set_ELM1   ELEKTROMAGNES |= _BV(ELM1) //wymusza stan niski
#define clr_ELM1   ELEKTROMAGNES &= ~_BV(ELM1) //wymusza stan wysoki
#define toggle_ELM1 ELEKTROMAGNES ^= _BV(ELM1)

#define set_ELM2   ELEKTROMAGNES |= _BV(ELM2) //wymusza stan niski
#define clr_ELM2   ELEKTROMAGNES &= ~_BV(ELM2) //wymusza stan wysoki
#define toggle_ELM2 ELEKTROMAGNES ^= _BV(ELM2)

#define probki 128
#define nieczulosc 3
signed int vh1,vh2,vh3,vh4,vh5,vh6,vh7,vh8,vh9,v10,v9,v8,v7,v6,adcz1,ADCval,a1,v;
unsigned char czujnik,wypelnienie1,wypelnienie2,adcz,licznik;



ISR(ADC_vect)// przerwanie dla przetwornika

{
	adcz+=ADC;// odczytana wartość dodawana jest do adcz
	licznik++;
	ADCSRA |= (1<<ADSC);

		if(licznik=probki)// wynik 128 probek
		{
			licznik=0;
			ADCval=adcz; //uaktualnienie zamiennej ADCval ( ona bedzie calkowana);

		if(ADCval>nieczulosc|ADCval<-nieczulosc) 
		{
			v=v+((ADCval+ADCval)>>1);

		}// calkowanie

		adcz=0;
		}
}

ISR(TIMER1_OVF_vect) 
	{
	set_ELM1;
	set_ELM2;
	sei();

		}

void ADC_init()
{
ADMUX=(1<<ADLAR)|(1<<MUX0);//0x21;//wyrownanie do lewej, zew vref, ADC1
ADCSRA=(1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);//0x9F; // prescaler 128,wlaczenie ADC, przerwania
}
void PWM_init()
{
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);
TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10);
}


int wait(void)// funkcja opozniajaca
{
int i;
	for(i=0;i<50;i++)
	{
	_delay_ms(50);
	asm volatile ("nop");
	}

}

int kalibracja(void)
{
lcd_puts("...");
wait();
LCD_CLEAR;
}

int main(void)
{
sei();
DDRA=0x00;
DDRB=0xFF;
DDRC=0xFC;
DDRD=0xFF;

PORTA=0x00;
PORTB=0x00;
PORTC=0x03;
PORTD=0x00;

double P_U[9];
P_U[0]=3.13;
P_U[1]=2.97;
P_U[2]=2.80;
P_U[3]=2.62;
P_U[4]=2.43;
P_U[5]=2.21;
P_U[6]=1.98;
P_U[7]=1.72;
P_U[8]=1.40;

char Po_U[5];

_delay_ms(10);

lcd_init();//inicjalizacja wyświetlacza
ADC_init();
TIMSK=(1<<TOIE1);
ADCSRA=(1<<ADSC);

	LCD_DISPLAY(LCDDISPLAY);//wlaczenie LCD

		lcd_puts("K");//wpisanie ciagu znaków
		_delay_ms(10);//opoznienie
		lcd_puts("W");
		_delay_ms(10);

	LCD_LOCATE(0,1);
		_delay_ms(10);
		lcd_puts("Politechnika Sl.");
		wait();

	LCD_CLEAR;

		lcd_puts(" Praca mgr inz.");
		wait();

	LCD_CLEAR;

		lcd_puts("Temat:");
		_delay_ms(10);
		lcd_puts(" UKLAD DO");
		_delay_ms(10);
	LCD_LOCATE(0,1);
		lcd_puts("TLUMIENIA UPADKU");
		wait();
	
	LCD_CLEAR;

while(1)
	{
	LCD_LOCATE(2,0);
		lcd_puts("Wybierz tryb");
		_delay_ms(10);
	LCD_LOCATE(4,1);
		lcd_puts(" pracy:");
		_delay_ms(10);
		wait();

	LCD_CLEAR;
		lcd_puts("1:Normalny");
		_delay_ms(10);
	LCD_LOCATE(0,1);
		lcd_puts("2:Awaryjny");
		while(1)
  		{
     
     	if(!(przycisk & 0x01))  /* Jeśli pierwszy przycisk wciśnięty */
     		{  

       		 _delay_ms(80);/* Czas na wygaśnięcie drgań styków przycisku*/  
    
   			while(!(przycisk & 0x01)) {}/* Oczekuje na zwolnienie przycisku*/

    		_delay_ms(80);/* Czas na wygaśnięcie drgań styków przycisku*/ 
			 
			LCD_CLEAR;

			lcd_puts(" Tryb awaryjny:");
			wait();

			LCD_CLEAR;

			LCD_LOCATE(3,0);
			lcd_puts("Kalibracja");
			_delay_ms(10);
			LCD_LOCATE(4,1);
			lcd_puts("Czujnika");
			wait();

			LCD_CLEAR;

			lcd_puts("Prosze czekac...");
			wait();
			wait();
			wait();
			wait();
			kalibracja();
			LCD_CLEAR;
			LCD_LOCATE(3,0);
			lcd_puts("Kalibracja");
			LCD_LOCATE(3,1);
			lcd_puts("zakonczona");
			wait();
			LCD_CLEAR;
			kalibracja();
			break;


			}
		if(!(przycisk & 0x02))/* Jeśli drugi przycisk wciśnięty */
    		{
       		 _delay_ms(80);
        	while(!(przycisk & 0x02)) {}
        	_delay_ms(80);

			LCD_CLEAR;
			LCD_LOCATE(3,0);
			lcd_puts("Zakonczenie");
			_delay_ms(10);
			LCD_LOCATE(2,1);
			lcd_puts("pracy ukladu");
			wait();
			wait();
			LCD_CLEAR;
			break;
			}
		}
	}

}


skoren86
-
Posty: 9
Rejestracja: 27 paź 2010, 16:10
Lokalizacja: Yawoźno

Post autor: skoren86 » 02 paź 2011, 18:15

Czy cos takiego ma mozliwość działania?

Kod: Zaznacz cały

ISR(ADC_vect)// przerwanie dla przetwornika
{
adc_mux=0x0F & ADMUX;

	adcz=ADCH;// odczytana z przetwornika ADC
	ADMUX++;
	ADCSRA |= (1<<ADSC);
	adcz1=adcz-a0;
	a1=a1+adcz1;
	if((adcz1<nieczulosc)&(adcz1>-nieczulosc)) //gdy wynik sumowania jest poniżej progu nieczułości
			 {mov++;}
	else {mov=0;}

	if(mov>25){v=0;}
	licznik++;

		if(licznik>32) //uśrednij wynik pomiaru z 32 próbek
		{	licznik=0;
			a1=(a1>>5);
		if(a1>nieczulosc|a1<-nieczulosc){v=v+((a1+a0p)>>1);} //całkowanie metodą trapezową
		a0p=a0;
		a0=0;
		}
	
		
}


ISR(TIMER1_OVF_vect) 
	{
	set_ELM1;
	set_ELM2;
	sei();
	if((v<=vh1)&(vh2<v)){ OCR1AL=0;OCR1BL=0;}
	if((v<=vh2)&(vh3<v)){ OCR1AL=0;OCR1BL=0;}
	if((v<=vh4)&(vh5<v)){ OCR1AL=0;OCR1BL=0;}
	if((v<=vh5)&(vh6<v)){ OCR1AL=0;OCR1BL=0;}
	if((v<=vh6)&(vh7<v)){ OCR1AL=0;OCR1BL=0;}
	if((v<=vh7)&(vh8<v)){ OCR1AL=0;OCR1BL=0;}
	if((v<=vh8)&(vh9<v)){ OCR1AL=0;OCR1BL=0;}
	if((v<=v1)&(v2<v)){ OCR1AL=64;OCR1BL=64;}
	if((v<=v2)&(v3<v)){ OCR1AL=128;OCR1BL=128;}
	if((v<=v3)&(v4<v)){ OCR1AL=192;OCR1BL=192;}
	if((v<=v4)&(v5<=v)){ OCR1AL=255;OCR1BL=255;}
	}


void ADC_init()
{
ADMUX=(1<<ADLAR)|(1<<MUX0);//0x21;//wyrownanie do lewej, zew vref, ADC1
ADCSRA=(1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);//0x9F; // prescaler 128,wlaczenie ADC, przerwania
}
void PWM_init()
{
TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);
TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10);
}

int main(void)
{
sei();
DDRA=0x00;
DDRB=0xFF;
DDRC=0xFC;
DDRD=0xFF;

PORTA=0x00;
PORTB=0x00;
PORTC=0x03;
PORTD=0x00;
ADC_init();
PWM_init();
TIMSK=(1<<TOIE1)|(1<<TOIE0);
ADCSRA|=(1<<ADSC);


double P_U[9]={vh9=3.13,vh8=2.97,vh7=2.80,vh6=2.62,vh5=2.43,vh4=2.21,vh3=1.98,vh2=1.72,vh1=1.40};

double Po_U[5]={v1=4,v2=4.5,v3=5,v4=5.5,v5=6};

while(1);
}

keruseykaryu

Post autor: keruseykaryu » 04 paź 2011, 5:30

Czy cos takiego ma mozliwość działania?
Symulator w dłonie i jazda. No chyba, że nie wiesz jak miał działać ten program.

skoren86
-
Posty: 9
Rejestracja: 27 paź 2010, 16:10
Lokalizacja: Yawoźno

Post autor: skoren86 » 06 paź 2011, 15:37

Tak wiem dobrze jak mial dzialac, tylko poprostu przeprowadzalem tak skomplikowany algorytm 1 raz, okazalo sie ze jednak jest do niczego :) temat mozna zamknac gdyz problem zostal rowiazany w bardzo prosty sposob, ktory rozswietlil droge w momencie uruchomienia calego ukladu :)

Pozdrawiam

ODPOWIEDZ