# Open-source Qibla finder with tilt compensation using 9-DoF IMU and GPS

After doing research on available designs on the internet for Qiblah compass devices, I found that the available ones are very few and miss an important feature of tilt compensation. As this device need obviously to be accurate, thus giving importance to improving accuracy is way more important than visual and sound effects. Therefore, I decided to build an open-source qiblah locator device built using Arduino, Magnetometer, GPS and an OLED display with proper documentation.

The first time I thought about the project was ten months ago, and after a study of what the project requires, I knew that I would need a Magnetometer and GPS receiver. That is why I bought Adafruit Mini GPS PA1010D and BMI270 shuttle board. The BMI270 with the BMM150 magnetometer is found in Arduino Nano 33 BLE Sense Rev2 too. Finally, I bought monochrome 0.91″ 128×32 I2C OLED Display to display the notifications to the user.

To reap, this Qiblah compass has the following features:

• Determining the Qibla using the magnetometer and/or the GPS receiver in case the circuit is likely to move for long distances.
• Tilt compensation.
• Magnetometer calibration.
• Open source for non-commercial purposes.
• Built with public and available circuits and easy to rebuild.
• Well documented.
The circuit was tested within the city in which I live. I hope anyone rebuilds it to confirm the correctness of the Qiblah location in his area.

## Magnetometer

The qiblah is a geographical direction, and to determine the geographical direction we use the magnetometer. Using it we can calculate the direction angle thanks to the geomagnetic field. The principle of calculating the direction using earth’s magnetic field is simple and shown in the figure below.

The angle can be calculated using the well-known trigonometric law: $\phi = \arctan(\frac{H_y}{H_x})$

By applying this equation, the calculated direction did not match my mobile compass. After searching about that problem, I found that the magnetometer suffers from distortion resulting from close magnetic fields generated by nearby circuits or magentis or from nearby materials that cause distortion of the geomagnetic field. This is called Soft iron calibration and Hard iron calibration. For this purpose, I wrote a detailed article on calibrating the magnetometer. Refer to it for a better understanding.

We will use the Motion Sensor Calibration Tool, which includes visualizing the received values and displaying statistics about them to ensure that they are good for the calibration process. It calculates the calibration matrices for the two types of Hard iron and Soft iron. The sensor values are sent to the program via serial communication at a speed of 115200 as follows:

Raw:acc_x,acc_y,acc_z,gyro_x,gyro_y,gyro_z,mag_x*10,mag_y*10,mag_z*10
To enable the circuit output needed for calibration, the value of the MOTION_CAL_SOFT macro is set to 1.

Be aware that the points in the 3D sphere of the calibration tool satisfy:

• Fit Erro as small as possible smaller than 1%.
• Gap as small as possible on the order of 0.2%.
• Variance to be as large as possible.

After the calibration matrix is calculated it is used in code to be used each time. There is a detailed lesson on using the Motion Sensor Calibration Tool program on YouTube for those who want to clarify it.

// Mag. calibration
// Hard ironing
//B
#define B1 -3.48
#define B2 0.42
#define B3 -5.78

//Soft ironing
//H column1
#define H11 1.036
#define H21 -0.023
#define H31 0.009
//H column2
#define H12 -0.023
#define H22 1.010
#define H32 -0.008
//H column3
#define H13 0.009
#define H23 -0.008
#define H33 0.956
/**********************/


After the calibration matrices are calculated, we use them in code. I recommend to refer to a detailed explanation of how to use the Motion Sensor Calibration Tool on Youtube.

Finally, the declination angle should be determined in the code. Use magnetic-declination.com to determine users depending on your location.

## OLED Display Screen

The used OLED screen from Adafruit has 128 pixels in width and 32 pixels in height. We will use 2 libraries Adafruit_GFX and Adafruit_SSD1306 to drive the Monochrome 0.91″ 128×32 I2C OLED Display.

To convert an image to be shown in the screen, we need to convert the image to a byte array. We will use LCD Assistant and although it is designed to work on Windows, it can run using Wine on Linux.

We import the BMP image from File>Load image, and use the following settings:

• Byte orientation:  Horizential
• Size: (image size max: 128×23)
• Size endinanness: Little
• Pixels/Byte: 8

To get the array, we do File>Save output. We use the generated array in the code using drawBitmap function.

To check the official documentation of the APIs used with the display like clearDisplay, display, setTextSize, and setCursor, the reader must refer to the official documentation

The code can operate using the magnetometer only, which gives the geographical direction which will be compared to the Qiblah’s angle. This is in the case of using the device on a fixed longitude and latitude. The latitude and longitude are set using constants in the program, YOUR_LAT and YOUR_LONG. To get the longitude and latitude, you can use the website latlong.net.

The code is also designed to work, if GPS is enabled, to calculate the Qibla direction when GPS_EN is set to 1. The receiver used works with the Adafruit_GPS library and is the Adafruit Mini GPS receiver. The GPS need to have what is called a “fix” in order to operate. The fix can not be achieved commonly without an open sky.

## Tilt Compensation

Most of the qiblah devices do not discuss the error caused by tilting the device, including pitching and rolling. It assumes to work on a flat surface which is an ideal case. The equation used in the magnetometer to calculate the direction assumes to have a flat surface. The solution of that problem is to preprocess the Magnetometer and tilt compensation. This plainly means to emulate that the device is on a flat surface, so the direction equation will be true. The error of the compass was caused by the tilt. The compensated compass angle was almost not affected by tilting the device.

A lot of application notes discuss the tilt compensation, and I recommend  Infineon-AN2272. It was explained in detail the frames and rotation matrixes in the third part of the published IMU serise. The rotation matrix used for tilt compensation is: $\left(\begin{array}{l}x \\ y \\ z\end{array}\right)=\left(\begin{array}{ccc}\cos \phi & \sin \theta \sin \phi & \cos \theta \sin \phi \\ 0 & \cos \theta & -\sin \theta \\ -\sin \phi & \sin \theta \cos \phi & \cos \theta \cos \phi\end{array}\right) \cdot\left(\begin{array}{l}x^{\prime} \\ y^{\prime} \\ z^{\prime}\end{array}\right)$

The first part of the published IMU serise discusses in detail how to calculate the pitch and roll angles.

## Calculating Qiblah angle

The equation derived and used to calculate the Qiblah is found below. The correct qibla reference is used to get the equation. $q=\tan ^{-1} \frac{\sin \left(\lambda_K-\lambda\right)}{\cos \phi \tan \phi_K-\sin \phi \cos \left(\lambda_K-\lambda\right)}$ $\lambda$ is the prayer longtidude $\phi$ is the prayer latitude $\lambda_K$ is Kaaba longitude which is  21.422510 $\phi_K$ is Kaaba latitude which is 39.826168

### Yahya Tawil

Embedded Hardware Engineer interested in open hardware and was born in the same year as Linux. Yahya is the editor-in-chief of Atadiat and believes in the importance of sharing free, practical, spam-free and high quality written content with others. His experience with Embedded Systems includes developing firmware with bare-metal C and Arduino, designing PCB&schematic and content creation.

This site uses Akismet to reduce spam. Learn how your comment data is processed.