LinkedIn YouTube Facebook
Szukaj

Wstecz
IoT

Kompas cyfrowy na STM32 i MAG3110

Jak widać aktualizacja wyświetlacza odbywa się tylko przy wybraniu nowej opcji z menu.
Gdy dokonamy wyboru poprzez naciśnięcie przycisku JOY_ENTER, wówczas program sprawdzi, która opcja menu była ostatnio wybrana i przejdzie do wykonania odpowiedniej funkcji:

    if (!GPIO_ReadInputDataBit(JOY_PORT_ENTER, JOY_ENTER))
      {
      switch (pozycja){
        case 1: Opcja_Info(); break;
        case 2: Opcja_Kalibracja(); break;
        case 3: Opcja_Kompas(); break;
        case 4: Opcja_Krzywe(); break;
      }
      aktualizacja=0;
    }   

Funkcje te wykonywane są do wciśnięcia JOY_DOWN. Pierwsza z nich to Opcja_INFO() :

void Opcja_Info(void){
  volatile unsigned long int i;
  TFTN_Clear(0x000);
  TFTN_WriteXY("     DEMO    \0"   ,  5, 10,0xFFF,0x000, font2);
  TFTN_WriteXY(" magnetometru\0",  5, 26,0xFFF,0x000, font2);
  TFTN_WriteXY("    MAG3110\0"   ,  5, 42,0xFFF,0x000, font2);
  TFTN_WriteXY("    UWAGA!!!\0"   ,  5, 68,0xFFF,0x000, font2);
  TFTN_WriteXY("  Dla wiarygodnego\0",  5, 82,0xFFF,0x000, font1);
  TFTN_WriteXY(" pomiaru ustaw os Z\0"   ,  5, 90,0xFFF,0x000, font1);
  TFTN_WriteXY("czujnika prostopadle\0",5,98,0xFFF,0x000, font1);
  TFTN_WriteXY("   do ziemi oraz\0",5,106,0xFFF,0x000, font1);
  TFTN_WriteXY("wykonaj kalibracje!!\0",5,114,0xFFF,0x000, font1);
  //Czekaj na JOY_DOWN
  while(GPIO_ReadInputDataBit(JOY_SW_PORT, JOY_DOWN)) ;
}

Ma ona za zadanie poinformować użytkownika o sposobie ustawienia i konfiguracji magnetometru, podkreślając by oś Z czujnika była ustawiona w przybliżeniu prostopadle do ziemi. Druga funkcja wybierana z opcji menu to Opcja_Kalibracja() :

void Opcja_Kalibracja(void)
{
volatile unsigned long int i;
volatile unsigned long int petla =500; //Czas kalibracji
signed short x, y,z;
signed short xmin=32767 ,xmax=-32768,ymin=32767,ymax=-32768;
extern signed short offsetx,offsety;
	
TFTN_Clear(0x000);
TFTN_WriteXY("  KALIBRACJA    \0"   ,  5, 10,0xFFF,0x000, font2);
TFTN_WriteXY("   UWAGA!!!  "   ,  5, 35,0xFFF,0x000, font2);
TFTN_WriteXY("W czasie trwania\0"   ,  5, 55,0xFFF,0x000, font1);
TFTN_WriteXY("sygnalu dzwiekowego\0",  5, 63,0xFFF,0x000, font1);
TFTN_WriteXY("dokonaj minimalnie \0"   ,  5, 71,0xFFF,0x000, font1);
TFTN_WriteXY("jednego obrotu \0",5,79,0xFFF,0x000, font1);
TFTN_WriteXY("czujnika wzgledem osi\0",5,87,0xFFF,0x000, font1);
TFTN_WriteXY("'Z' ustawionej do \0",5,95,0xFFF,0x000, font1);
TFTN_WriteXY("ziemi prostopadle\0",5,103,0xFFF,0x000, font1);
TFTN_WriteXY("Wcisnij JOY_ENTER\0",5,121,0xFFF,0x000, font1);
//Czekaj na JOY_ENTER
while(GPIO_ReadInputDataBit(JOY_PORT_ENTER, JOY_ENTER));
//Wyznaczanie minimalnych i maksymalnych wartosci pola magnetycznego na osiach X i Y
//po wykonaniu co najminej jednego obrotu czujnika wokol osi Z ustawionej prostopadle
//do ziemi
	while (petla)
	{
		MAG3110_GetPosition(&x, &y, &z);
		
		if (x<xmin) xmin=x; if (x>xmax) xmax=x;
		
		if (y<ymin) ymin=y; if (y>ymax) ymax=y;
		
		petla--;
		
		//W czasie kalibracji Speaker wydaje dzwiek
		GPIO_WriteBit(GPIOB, GPIO_Pin_12, (BitAction).....
		....(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12)));
	}
	
	//Przesuniecie ukladu wspolrzednych tak aby
	//jego srodek znajdowal sie w polowie roznicy minimalnego i maksymalnego
	//pola magnetycznego odczytanego przez magnetometr dla osi X oraz Y
	offsetx=abs((xmin+xmax)*0.5);
	if (abs(xmin)<xmax) offsetx=-offsetx;
	
	offsety=abs((ymin+ymax)*0.5);
	if (abs(ymin)<ymax) offsety=-offsety;
	
}

Funkcja cyklicznie odczytuje wartość pola magnetycznego z czujnika dla każdej osi za pomocą funkcji:

void MAG3110_GetPosition(signed short * x,signed short * y, signed short * z)
{
  //reads 5 registers values into buffer in multiple bytes mode, buffer[0]=x, [2]=z, [3]=y
  unsigned char Bufor[6]={0};
  unsigned int NumByteToReadN, i;
  //Check, if I2C is free
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
  I2C_GenerateSTART(I2C1,ENABLE);
  //Test on EV5 and clear it
  while(!I2C_CheckEvent(MAG3110_I2C, I2C_EVENT_MASTER_MODE_SELECT));  
  //Send MAG3110 address, set I2C master in transmiter mode
  I2C_Send7bitAddress(MAG3110_I2C, MAG3110_Addr, I2C_Direction_Transmitter);
  //Test on EV6 and clear it
  while(!I2C_CheckEvent(MAG3110_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  //Send base register address, set address autoincrement
  I2C_SendData(MAG3110_I2C, 0x01);
  //Test on EV8 and clear it
  while(!I2C_CheckEvent(MAG3110_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  //Re-generate START, transmition from slave beginning
  I2C_GenerateSTART(MAG3110_I2C,ENABLE);
  //Test on EV5 and clear it
  while(!I2C_CheckEvent(MAG3110_I2C, I2C_EVENT_MASTER_MODE_SELECT));
  //Send MAG3110 address, set I2C master in receiver mode
  I2C_Send7bitAddress(MAG3110_I2C, MAG3110_Addr, I2C_Direction_Receiver);
  //Test on EV6 and clear it
  while(!I2C_CheckEvent(MAG3110_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
  NumByteToReadN=6;  //Read 6 consecutive registers
  i=0;               //Current read count
  while(NumByteToReadN) {
    //Before receiving last byte, disable acknowledge and generate stop
    if(NumByteToReadN == 1) {
      I2C_AcknowledgeConfig(MAG3110_I2C, DISABLE);
      I2C_GenerateSTOP(MAG3110_I2C, ENABLE);
    }
    //Test on EV7 and clear it
    while(!I2C_CheckEvent(MAG3110_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED));
    //Read a byte from the MAG3110
    Bufor[i] = I2C_ReceiveData(MAG3110_I2C);
    i++;
    NumByteToReadN--;
  }
  //Enable Acknowledge for next transmission
  I2C_AcknowledgeConfig(MAG3110_I2C, ENABLE);
  //Assign data to axis variables	
  *x=(signed short)((Bufor[0]<<8)|Bufor[1]);
  *y=(signed short)((Bufor[2]<<8)|Bufor[3]);
  *z=(signed short)((Bufor[4]<<8)|Bufor[5]);
}