Operácie

Projekt: Dvojosí akcelerometer B: Rozdiel medzi revíziami

Z SensorWiki

(Vytvorená stránka „Sem príde správa z riešenia projektu. Category:AVR Category:DVPS“)
 
 
(7 medziľahlých úprav od jedného ďalšieho používateľa nie je zobrazených)
Riadok 1: Riadok 1:
Sem príde správa z riešenia projektu.
+
*Vypracovali:
 +
:::::'''Bc. Lukáš Topoli'''
 +
:::::'''Bc. Edvin Virág'''
 +
 
 +
 
 +
*Študijný odbor: '''Aplikovaná mechatronika'''                            
 +
*Ročník: '''2. Ing.'''
 +
 
 +
 
 +
== Zadanie ==
 +
 
 +
#Zobrazte na LCD náklon dosky v dvoch osiach zmeraný snímačom Memsic (meranie šírky impulzov).
 +
#Implementujte rolovanie dlhého textu na LCD displeji podľa náklonu.
 +
 
 +
[[Obrázok:SnimacZrychleniaMemsic.jpg]]
 +
 
 +
'''Literatúra:'''
 +
 
 +
* [http://www.parallax.com/StoreSearchResults/tabid/768/txtSearch/memsic/List/0/SortField/4/ProductID/93/Default.aspx Product Page] (parallax.com)
 +
* [http://www.parallax.com/Portals/0/Downloads/docs/prod/acc/memsickit.pdf Datasheet]
 +
* [http://www.parallax.com/Portals/0/Downloads/docs/prod/sens/28017-Memsic2Axis-v2.0.pdf Sensor datasheet]
 +
 
 +
 
 +
 
 +
== Akcelerometer ==
 +
 
 +
 
 +
MEMSIC 2125 je low-cost tepelný akcelerometer. Snima v dvoch osiach: náklon, zrýchlenie pri kolízii, statické a dynamické zrýchlenie, natočenie a vibrácie s rozsahom ±3g.
 +
 
 +
[[Súbor:topoli_fotka_akcel.png]]
 +
'''Obr. 1: Dvojosí akcelerometer Memsic 2125'''
 +
 
 +
'''Základné parametre:'''
 +
*Meranie zrýchlenia s rozsahom ±3 g na oboch osiach
 +
*Jednoduchý impulzný výstup pre obe osi
 +
*Analógový výstup teploty (Tout pin)
 +
*Rozsah prevádzkových teplôt 0 až 70 °C
 +
*Rozsah napájacieho napätia: 3,3 – 5 V
 +
*Komunikácia: TTL/CMOS kompatibilné 100Hz PWM výstupný signál je úmerný zrýchleniu
 +
 
 +
 
 +
 
 +
'''Piny akcelerometra:'''
 +
 
 +
[[Súbor:topoli_piny_akcel.png]]
 +
'''Obr. 2: Piny akcelerometra'''
 +
 
 +
Výstupy akcelerometra:
 +
1 Tout teplota
 +
2 Yout PWM výstup osi Y
 +
3 GND Uzemnenie (0 V)
 +
4 GND Uzemnenie (0 V)
 +
5 Xout PWM výstup osi X
 +
6 Vdd Napájacie napätie (5 V)
 +
 
 +
== Riešenie úlohy ==
 +
 
 +
Zapojenie akcelerometra na vývojovej doske acrob:
 +
 
 +
[[Súbor:topoli_zapojenie_akcel.png]]
 +
'''Obr. 3: Zapojenie akcelerometra'''
 +
 
 +
Každá z osí akcelerometra generuje na výstupe 100Hz PWM signál. Strieda signálu záleží od smeru a veľkosti zrýchlenia.
 +
 
 +
 
 +
[[Súbor:topoli_pwm.png]]
 +
'''Obr. 4: PWM modulácia'''
 +
 
 +
 
 +
Zrýchlenie je úmerné podielu tHx/Tx. Pri napájacom napätí 5 V, 50% pracovného cyklu zodpovedá nulovému zrýchleniu 0g.
 +
 
 +
[[Súbor:topoli_perioda.png]]
 +
'''Obr. 5:  '''
 +
 
 +
Počítadlo je 16 bitové to je 56536 vzoriek, pri 16MHz musí byť preddelička minimálne clk/8 (20 000vzoriek/10ms). Preddelička je nastavená na clk/8. Teda 16MHz/8 = 2 MHz frekvencia vzorkovania, teda 20 000 vzoriek za 10ms. Presnosť akcelerometra je 1 mg to znamená 4 000 vzoriek v jeho rozsahu +/-2g (10ms).  Keďže 20 000(presnosť 0,2mg) > 4 000 presnosť merania je 1mg. (V prípade použitia preddeličky clk/16 by bola presnosť 1,6mg).
 +
 
 +
Tok textu v osi x je zabezpečený posúvaním kurzoru displeja a vypísaním riadku matice.
 +
Tok textu v osi y je spravený vypísaním následujúceho riadoku matice.
 +
 
 +
== Zdrojový kód ==
 +
 
 +
Potrebné súbory: [[lcd.c]] [[lcd.h]] [[AkcelerometerTopoliVirag.c‎]]
 +
 
 +
 
 +
Kód v jayzku C:
 +
<source lang="c">
 +
#include <stdlib.h>
 +
#include <stdio.h>
 +
#include <avr/io.h>
 +
#include "lcd.h"
 +
#include <avr/interrupt.h> 
 +
 
 +
 
 +
// PWM X
 +
 
 +
volatile unsigned int Xzaciatok = 0; 
 +
volatile long int XPWM=0;
 +
volatile unsigned int Xkoniec=0;
 +
volatile unsigned int Xaktualne=0;
 +
volatile long rozdielX;
 +
volatile unsigned int dobeznaX=0;
 +
 
 +
// PWM Y
 +
volatile unsigned int Yzaciatok = 0; 
 +
volatile long int YPWM=0;
 +
volatile unsigned int Ykoniec=0;
 +
volatile unsigned int Yaktualne=0;
 +
volatile long rozdielY;
 +
volatile unsigned int dobeznaY=0;
 +
 
 +
 
 +
FILE mystdout = FDEV_SETUP_STREAM(lcdDataWrite, NULL, _FDEV_SETUP_WRITE); // nová funkcia pre jeden znak
 +
 
 +
unsigned char pole[8][16]={"1x65456798776549","2xMOIJNKZHGFRTWD","3xjkreiooasjkrpl","4x@#$%^&*()_+}|:","5x65456798776549","6xMOIJNKZHGFRTWD","7xjkreiooasjkrpl","8x@#$%^&*()_+}|:"};
 +
 
 +
ISR(PCINT0_vect) //  X prerušenie
 +
{
 +
//hodnota countra pri prerušení
 +
Xaktualne=TCNT1;
 +
 
 +
// dobežná hrana
 +
if (!(PINB & 0b00100000))
 +
// sirka impulzu dobezna
 +
{
 +
dobeznaX=Xaktualne;
 +
XPWM=dobeznaX-Xzaciatok;
 +
if (XPWM<=0)
 +
{
 +
XPWM=dobeznaX+65536-Xzaciatok;
 +
}
 +
}
 +
else
 +
// sirka impulzu nabezna
 +
{
 +
 +
Xkoniec=Xzaciatok;
 +
Xzaciatok=Xaktualne;
 +
rozdielX=Xzaciatok-Xkoniec;
 +
if (rozdielX <=0)
 +
{
 +
rozdielX=Xzaciatok+65536-Xkoniec;
 +
}
 +
}
 +
}
 +
 
 +
ISR(PCINT1_vect) //  Y prerušenie
 +
{
 +
//hodnota countra pri prerušení
 +
Yaktualne=TCNT1;
 +
 
 +
// nábežná hrana
 +
if (PINC & 0b00000001)
 +
// sirka impulzu nabezna
 +
{
 +
Ykoniec=Yzaciatok;
 +
Yzaciatok=Yaktualne;
 +
rozdielY=Yzaciatok-Ykoniec;
 +
if (rozdielY <=0)
 +
{
 +
rozdielY=Yzaciatok+65536-Ykoniec;
 +
}
 +
}
 +
else
 +
// sirka impulzu dobezna
 +
{
 +
dobeznaY=Yaktualne;
 +
YPWM=dobeznaY-Yzaciatok;
 +
if (YPWM<=0)
 +
{
 +
YPWM=dobeznaY+65536-Yzaciatok;
 +
}
 +
}
 +
}
 +
 
 +
 
 +
 
 +
//oneskorenie, milisekundy
 +
 
 +
void delay_ms(unsigned int ms)
 +
{
 +
  unsigned int index;
 +
 
 +
  while (ms)
 +
  {
 +
  index = F_CPU / 19040;   
 +
       
 +
  while (index)
 +
  {
 +
    asm volatile ("nop");
 +
    index--;
 +
  }
 +
 
 +
  ms--;
 +
  }
 +
}
 +
 
 +
 
 +
int main(void)
 +
{
 +
 +
DDRB = 0b00000000;              // nastav ICR - Port B, pin0  ako INPUT
 +
DDRC = 0b00000000;              // nastav ICR - Port C, pin5  ako INPUT
 +
PCICR=0b00000011; // nastavenie externého prerušenia
 +
PCIFR=0b00000011;
 +
PCMSK1=0b00000001;
 +
PCMSK0=0b00100000;
 +
 
 +
TCCR1B = 0b11000010;              // T1 clk = F_CPU : 1024, falling edge pin ICP1,
 +
TCCR1A = 0b00000000;                // T1 in timer mode !! Note: if You omit this, TCNT1 will be only 8-bit !!
 +
  TCNT1 = 0x0000;          // inicializácia poèítadla (16-bit! Low+High bytes)
 +
lcdInit4();
 +
stdout = &mystdout;          // Odteraz funguje printf();
 +
sei();                    // povolenie všetkých prerušení 
 +
 
 +
int i=0,j=0;
 +
 
 +
 
 +
int cislo=0;
 +
int k1=0;
 +
 
 +
for(;;){
 +
 
 +
//dozadu
 +
if (YPWM > 10000){
 +
cislo=12000-((YPWM-rozdielY)+20000);
 +
if (cislo<=0)
 +
cislo=0;
 +
lcdControlWrite(1<<LCD_CLR);
 +
lcdControlWrite(0x80);
 +
lcdControlWrite(0x80+4+k1);
 +
for(i=0;i<10;i++){
 +
lcdDataWrite(pole[j][i]);
 +
}
 +
 
 +
lcdControlWrite(0x80+0x40+4+k1);
 +
for(i=0;i<10;i++){
 +
lcdDataWrite(pole[j+1][i]);
 +
}
 +
 
 +
delay_ms(cislo);
 +
j++;
 +
if(j==7)
 +
j=0;
 +
}
 +
//dopredu
 +
if (YPWM < 9500){
 +
cislo=12000-(rozdielY-YPWM);
 +
if (cislo<=0)
 +
cislo=0;
 +
lcdControlWrite(1<<LCD_CLR);
 +
lcdControlWrite(0x80);
 +
lcdControlWrite(0x80+4+k1);
 +
for(i=0;i<10;i++){
 +
lcdDataWrite(pole[j][i]);
 +
}
 +
 
 +
lcdControlWrite(0x80+0x40+4+k1);
 +
for(i=0;i<10;i++){
 +
lcdDataWrite(pole[j+1][i]);
 +
}
 +
delay_ms(cislo);
 +
j--;
 +
if(j<0)
 +
j=6;
 +
}
 +
//doprava
 +
if (XPWM > 10000){
 +
cislo=12000-((XPWM-rozdielX)+20000);
 +
if (cislo<=0)
 +
cislo=0;
 +
lcdControlWrite(1<<LCD_CLR);
 +
lcdControlWrite(0x80);
 +
lcdControlWrite(0x80+4+k1);
 +
for(i=0;i<10;i++){
 +
lcdDataWrite(pole[j][i]);
 +
}
 +
 
 +
lcdControlWrite(0x80+0x40+4+k1);
 +
for(i=0;i<10;i++){
 +
lcdDataWrite(pole[j+1][i]);
 +
}
 +
delay_ms(cislo);
 +
k1++;
 +
if(k1==4)
 +
{
 +
k1=-4;
 +
}
 +
}
 +
//dolava
 +
if (XPWM < 9500){
 +
cislo=12000-(rozdielX-XPWM);
 +
if (cislo<=0)
 +
cislo=0;
 +
lcdControlWrite(1<<LCD_CLR);
 +
lcdControlWrite(0x80);
 +
lcdControlWrite(0x80+4+k1);
 +
for(i=0;i<10;i++){
 +
lcdDataWrite(pole[j][i]);
 +
}
 +
 
 +
lcdControlWrite(0x80+0x40+4+k1);
 +
for(i=0;i<10;i++){
 +
lcdDataWrite(pole[j+1][i]);
 +
}
 +
delay_ms(cislo);
 +
k1--;
 +
if(k1<=-5)
 +
{
 +
k1=3;
 +
}
 +
}
 +
}
 +
}
 +
 
 +
 
 +
</source>
 +
 
  
 
[[Category:AVR]] [[Category:DVPS]]
 
[[Category:AVR]] [[Category:DVPS]]

Aktuálna revízia z 14:03, 18. november 2013

  • Vypracovali:
Bc. Lukáš Topoli
Bc. Edvin Virág


  • Študijný odbor: Aplikovaná mechatronika
  • Ročník: 2. Ing.


Zadanie

  1. Zobrazte na LCD náklon dosky v dvoch osiach zmeraný snímačom Memsic (meranie šírky impulzov).
  2. Implementujte rolovanie dlhého textu na LCD displeji podľa náklonu.

SnimacZrychleniaMemsic.jpg

Literatúra:


Akcelerometer

MEMSIC 2125 je low-cost tepelný akcelerometer. Snima v dvoch osiach: náklon, zrýchlenie pri kolízii, statické a dynamické zrýchlenie, natočenie a vibrácie s rozsahom ±3g.

Topoli fotka akcel.png Obr. 1: Dvojosí akcelerometer Memsic 2125

Základné parametre:

  • Meranie zrýchlenia s rozsahom ±3 g na oboch osiach
  • Jednoduchý impulzný výstup pre obe osi
  • Analógový výstup teploty (Tout pin)
  • Rozsah prevádzkových teplôt 0 až 70 °C
  • Rozsah napájacieho napätia: 3,3 – 5 V
  • Komunikácia: TTL/CMOS kompatibilné 100Hz PWM výstupný signál je úmerný zrýchleniu


Piny akcelerometra:

Topoli piny akcel.png Obr. 2: Piny akcelerometra

Výstupy akcelerometra: 1 Tout teplota 2 Yout PWM výstup osi Y 3 GND Uzemnenie (0 V) 4 GND Uzemnenie (0 V) 5 Xout PWM výstup osi X 6 Vdd Napájacie napätie (5 V)

Riešenie úlohy

Zapojenie akcelerometra na vývojovej doske acrob:

Topoli zapojenie akcel.png Obr. 3: Zapojenie akcelerometra

Každá z osí akcelerometra generuje na výstupe 100Hz PWM signál. Strieda signálu záleží od smeru a veľkosti zrýchlenia.


Topoli pwm.png Obr. 4: PWM modulácia


Zrýchlenie je úmerné podielu tHx/Tx. Pri napájacom napätí 5 V, 50% pracovného cyklu zodpovedá nulovému zrýchleniu 0g.

Topoli perioda.png Obr. 5:

Počítadlo je 16 bitové to je 56536 vzoriek, pri 16MHz musí byť preddelička minimálne clk/8 (20 000vzoriek/10ms). Preddelička je nastavená na clk/8. Teda 16MHz/8 = 2 MHz frekvencia vzorkovania, teda 20 000 vzoriek za 10ms. Presnosť akcelerometra je 1 mg to znamená 4 000 vzoriek v jeho rozsahu +/-2g (10ms). Keďže 20 000(presnosť 0,2mg) > 4 000 presnosť merania je 1mg. (V prípade použitia preddeličky clk/16 by bola presnosť 1,6mg).

Tok textu v osi x je zabezpečený posúvaním kurzoru displeja a vypísaním riadku matice. Tok textu v osi y je spravený vypísaním následujúceho riadoku matice.

Zdrojový kód

Potrebné súbory: lcd.c lcd.h AkcelerometerTopoliVirag.c‎


Kód v jayzku C:

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


		// PWM X

volatile unsigned int Xzaciatok = 0;   	
volatile long int XPWM=0;
volatile unsigned int Xkoniec=0;
volatile unsigned int Xaktualne=0;
volatile long rozdielX;
volatile unsigned int dobeznaX=0;

		// PWM Y
volatile unsigned int Yzaciatok = 0;   	
volatile long int YPWM=0;
volatile unsigned int Ykoniec=0;
volatile unsigned int Yaktualne=0;
volatile long rozdielY;
volatile unsigned int dobeznaY=0;


FILE mystdout = FDEV_SETUP_STREAM(lcdDataWrite, NULL, _FDEV_SETUP_WRITE);		// nová funkcia pre jeden znak

unsigned char pole[8][16]={"1x65456798776549","2xMOIJNKZHGFRTWD","3xjkreiooasjkrpl","4x@#$%^&*()_+}|:","5x65456798776549","6xMOIJNKZHGFRTWD","7xjkreiooasjkrpl","8x@#$%^&*()_+}|:"};

ISR(PCINT0_vect)					//  X prerušenie
{
//hodnota countra pri prerušení
Xaktualne=TCNT1;						

			// dobežná hrana
if (!(PINB & 0b00100000))	
	// sirka impulzu dobezna
	{
	dobeznaX=Xaktualne;		
	XPWM=dobeznaX-Xzaciatok;
	if (XPWM<=0)
	{
	XPWM=dobeznaX+65536-Xzaciatok;
	}
	}
	else
	// sirka impulzu nabezna
	{
					
	Xkoniec=Xzaciatok;
	Xzaciatok=Xaktualne;
	rozdielX=Xzaciatok-Xkoniec;
	if (rozdielX <=0)
	{
	rozdielX=Xzaciatok+65536-Xkoniec;
	}
	}
}

ISR(PCINT1_vect)					//  Y prerušenie
{
//hodnota countra pri prerušení
Yaktualne=TCNT1;			

// nábežná hrana
if (PINC & 0b00000001)					
	// sirka impulzu nabezna
	{
		Ykoniec=Yzaciatok;				
	Yzaciatok=Yaktualne;
	rozdielY=Yzaciatok-Ykoniec;
	if (rozdielY <=0)
	{
	rozdielY=Yzaciatok+65536-Ykoniec;
	}
	}
	else
	// sirka impulzu dobezna
	{
	dobeznaY=Yaktualne;				
		YPWM=dobeznaY-Yzaciatok;
			if (YPWM<=0)
	{
	YPWM=dobeznaY+65536-Yzaciatok;
	}
	}
}



	//oneskorenie, milisekundy

void delay_ms(unsigned int ms)			
{
  unsigned int index;

  while (ms)
  {
  index = F_CPU / 19040;    				
        
   while (index)
   {
    asm volatile ("nop");
    index--;
   }

   ms--;
  }
}


int main(void)
{
	
	DDRB = 0b00000000;              			// nastav ICR - Port B, pin0  ako INPUT
	DDRC = 0b00000000;              			// nastav ICR - Port C, pin5  ako INPUT
	PCICR=0b00000011;				// nastavenie externého prerušenia
	PCIFR=0b00000011;			
	PCMSK1=0b00000001;
	PCMSK0=0b00100000;

 TCCR1B = 0b11000010;               			// T1 clk = F_CPU : 1024, falling edge pin ICP1,
 TCCR1A = 0b00000000;                			// T1 in timer mode !! Note: if You omit this, TCNT1 will be only 8-bit !!
  TCNT1 = 0x0000;           				// inicializácia poèítadla (16-bit! Low+High bytes)
lcdInit4();
 stdout = &mystdout;           				// Odteraz funguje printf();
sei();                    				// povolenie všetkých prerušení  

int i=0,j=0;


int cislo=0;
int k1=0;

for(;;){

//dozadu
if (YPWM > 10000){
cislo=12000-((YPWM-rozdielY)+20000);
if (cislo<=0)
cislo=0;
lcdControlWrite(1<<LCD_CLR);
lcdControlWrite(0x80);
lcdControlWrite(0x80+4+k1);
for(i=0;i<10;i++){
lcdDataWrite(pole[j][i]);
}

lcdControlWrite(0x80+0x40+4+k1);
for(i=0;i<10;i++){
lcdDataWrite(pole[j+1][i]);
}

delay_ms(cislo);
j++;
if(j==7)
j=0;
}
//dopredu
if (YPWM < 9500){
cislo=12000-(rozdielY-YPWM);
if (cislo<=0)
cislo=0;
lcdControlWrite(1<<LCD_CLR);
lcdControlWrite(0x80);
lcdControlWrite(0x80+4+k1);
for(i=0;i<10;i++){
lcdDataWrite(pole[j][i]);
}

lcdControlWrite(0x80+0x40+4+k1);
for(i=0;i<10;i++){
lcdDataWrite(pole[j+1][i]);
}
delay_ms(cislo);
j--;
if(j<0)
j=6;
}
//doprava
if (XPWM > 10000){
cislo=12000-((XPWM-rozdielX)+20000);
if (cislo<=0)
cislo=0;
lcdControlWrite(1<<LCD_CLR);
lcdControlWrite(0x80);
lcdControlWrite(0x80+4+k1);
for(i=0;i<10;i++){
lcdDataWrite(pole[j][i]);
}

lcdControlWrite(0x80+0x40+4+k1);
for(i=0;i<10;i++){
lcdDataWrite(pole[j+1][i]);
}
delay_ms(cislo);
k1++;
if(k1==4)
{
k1=-4;
}
}
//dolava
if (XPWM < 9500){
cislo=12000-(rozdielX-XPWM);
if (cislo<=0)
cislo=0;
lcdControlWrite(1<<LCD_CLR);
lcdControlWrite(0x80);
lcdControlWrite(0x80+4+k1);
for(i=0;i<10;i++){
lcdDataWrite(pole[j][i]);
}

lcdControlWrite(0x80+0x40+4+k1);
for(i=0;i<10;i++){
lcdDataWrite(pole[j+1][i]);
}
delay_ms(cislo);
k1--;
if(k1<=-5)
{
k1=3;
}
}
}
}