LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
IoT

Cyfrowy kompas na STM32 z czujnikiem HMC5883

Jak widać aktualizacja treści 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("    HMC588L\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)
	{
		HMC5883L_GetPosition(&x, &y, &z);
		
		if (xxmax) xmax=x;
		
		if (yymax) 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)

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

void HMC5883L_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(HMC5883L_I2C, I2C_EVENT_MASTER_MODE_SELECT));  
  //Send HMC5883L address, set I2C master in transmiter mode
  I2C_Send7bitAddress(HMC5883L_I2C, HMC5883L_Addr, I2C_Direction_Transmitter);
  //Test on EV6 and clear it
  while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  //Send base register address, set address autoincrement
  I2C_SendData(HMC5883L_I2C, 0x03);
  //Test on EV8 and clear it
  while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  //Re-generate START, transmition from slave beginning
  I2C_GenerateSTART(HMC5883L_I2C,ENABLE);
  //Test on EV5 and clear it
  while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_MODE_SELECT));
  //Send HMC5883L address, set I2C master in receiver mode
  I2C_Send7bitAddress(HMC5883L_I2C, HMC5883L_Addr, I2C_Direction_Receiver);
  //Test on EV6 and clear it
  while(!I2C_CheckEvent(HMC5883L_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(HMC5883L_I2C, DISABLE);
      I2C_GenerateSTOP(HMC5883L_I2C, ENABLE);
    }
    //Test on EV7 and clear it
    while(!I2C_CheckEvent(HMC5883L_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED));
    //Read a byte from the HMC5883L
    Bufor[i] = I2C_ReceiveData(HMC5883L_I2C);
    i++;
    NumByteToReadN--;        
  }

  //Enable Acknowledge for next transmission
  I2C_AcknowledgeConfig(HMC5883L_I2C, ENABLE);

  //Assign data to axis variables	

  *x=(signed short)((Bufor[0]<<8)|Bufor[1]);
  *z=(signed short)((Bufor[2]<<8)|Bufor[3]);
  *y=(signed short)((Bufor[4]<<8)|Bufor[5]);
}

Do pobrania