|
| 1 | +--- |
| 2 | +title: Screen Orientation With IMU Readings |
| 3 | +description: "Learn how to use the GIGA Display Shield's IMU to determine the shield's orientation." |
| 4 | +author: Benjamin Dannegård |
| 5 | +tags: [Display, IMU, orientation, LVGL] |
| 6 | +--- |
| 7 | + |
| 8 | +Any modern device with a screen uses sensors to determine the correct orientation in which an image should be displayed. Using the Arduino GIGA R1 WiFi with the GIGA Display Shield we can read values given by the onboard IMU to determine what orientation an image should be given. This tutorial will show you how to manipulate an image on the GIGA Display Shield using LVGL and readings from the IMU sensor. |
| 9 | + |
| 10 | +## Hardware & Software Needed |
| 11 | + |
| 12 | +- [Arduino GIGA R1 WiFi](/hardware/giga-r1) |
| 13 | +- [Arduino GIGA Display Shield]() |
| 14 | +- [Arduino IDE](https://www.arduino.cc/en/software) |
| 15 | +- [Arduino_BMI270_BMM150 library](https://reference.arduino.cc/reference/en/libraries/arduino_bmi270_bmm150/) |
| 16 | +- [Arduino_H7_Video library](https://github.com/arduino/ArduinoCore-mbed/tree/main/libraries/Arduino_H7_Video) |
| 17 | +- [LVGL library](https://reference.arduino.cc/reference/en/libraries/lvgl/) |
| 18 | + |
| 19 | +## Downloading the Library and Core |
| 20 | + |
| 21 | +Make sure the latest GIGA Core is installed in the Arduino IDE. **Tools > Board > Board Manager...**. Here you need to look for the **Arduino Mbed OS Giga Boards** and install it. Now you have to install the library needed for the IMU and the library for handling the image. Go to **Tools > Manage libraries..**, search for **Arduino_BMI270_BMM150**, and install it. This library will help us with reading values from the IMU. Now search for **LVGL**, and install it. This library will be used for the image and rotating it. |
| 22 | + |
| 23 | +## Using the IMU Readings With the Image |
| 24 | + |
| 25 | +Now to first get the readings from the IMU we will use the `"Arduino_BMI270_BMM150.h"` library. The `"Arduino_H7_Video.h"` and `"lvgl.h"` libraries will help us handle the image. Set up the display dimensions with `Arduino_H7_Video Display(800, 480, GigaDisplayShield);`. To use the IMU set it up with `BoschSensorClass imu(Wire1);`. Next, we can give the image its attributes. |
| 26 | + |
| 27 | +```arduino |
| 28 | +#include "Arduino_BMI270_BMM150.h" |
| 29 | +#include "Arduino_H7_Video.h" |
| 30 | +#include "lvgl.h" |
| 31 | +
|
| 32 | +Arduino_H7_Video Display(800, 480, GigaDisplayShield); /* Arduino_H7_Video Display(1024, 768, USBCVideo); */ |
| 33 | +
|
| 34 | +BoschSensorClass imu(Wire1); |
| 35 | +``` |
| 36 | + |
| 37 | +Start receiving IMU readings with `imu.begin();` and start the display with `Display.begin();`. Then we can assign attributes to the images such as its source, alignment and how the rotation should behave. For more information on image attributes with LVGL, check out our [LVGL tutorial](lvgl-guide#image). |
| 38 | + |
| 39 | +```arduino |
| 40 | +LV_IMG_DECLARE(img_arduinologo); |
| 41 | +lv_obj_t * img; |
| 42 | +
|
| 43 | +void setup() { |
| 44 | + Serial.begin(115200); |
| 45 | + |
| 46 | + Display.begin(); |
| 47 | + imu.begin(); |
| 48 | +
|
| 49 | + img = lv_img_create(lv_scr_act()); |
| 50 | + lv_img_set_src(img, &img_arduinologo); |
| 51 | + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); |
| 52 | + lv_img_set_pivot(img, (img_arduinologo.header.w)/2, (img_arduinologo.header.h)/2); /* Rotate around the center of the image */ |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +Now all that is left is to change the image depending on the IMU readings. First, declare the variables that will hold the values. Then to assign them the IMU reading values use `imu.readAcceleration(x, y, z);`. Next, we use `if ()` statements to change the rotation variable depending on the readings we are getting. And at the end, we render the image with the correct rotation. When the correct rotation has been calculated, we can apply it to the image using `lv_img_set_angle(img, rot_angle);`. |
| 57 | + |
| 58 | +```arduino |
| 59 | +uint8_t rotation = 0; |
| 60 | +
|
| 61 | +void loop() { |
| 62 | + float x, y, z; |
| 63 | + if (imu.accelerationAvailable()) { |
| 64 | + imu.readAcceleration(x, y, z); |
| 65 | + if ( z < 0.8 && z > -0.8) { |
| 66 | + if (x < -0.8) { |
| 67 | + rotation = 0; |
| 68 | + } else if (x > 0.8) { |
| 69 | + rotation = 2; |
| 70 | + } else if (y < -0.8) { |
| 71 | + rotation = 1; |
| 72 | + } else if (y > 0.8) { |
| 73 | + rotation = 3; |
| 74 | + } |
| 75 | + int16_t rot_angle = 900 - atan(x / y) * 180.0 / M_PI * 10; //Calculation for the rotation angle |
| 76 | + lv_img_set_angle(img, rot_angle); |
| 77 | + } |
| 78 | + } |
| 79 | + lv_timer_handler(); |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +### IMU Test Sketch |
| 84 | + |
| 85 | +The easiest way to tell what values you are getting depending on the orientation of the device is to use a simple sketch, like the one below that will print the IMU values in the serial monitor. Take note of the values you are getting when you rotate the shield and you can use them in the full sketch. |
| 86 | + |
| 87 | +```arduino |
| 88 | +#include "Arduino_BMI270_BMM150.h" |
| 89 | +
|
| 90 | +BoschSensorClass imu(Wire1); |
| 91 | +
|
| 92 | +void setup(){ |
| 93 | + Serial.begin(115200); |
| 94 | + imu.begin(); |
| 95 | +} |
| 96 | +
|
| 97 | +void loop(){ |
| 98 | + float x, y, z; |
| 99 | + if (imu.accelerationAvailable()) { |
| 100 | + imu.readAcceleration(x, y, z); |
| 101 | + Serial.print(x); |
| 102 | + Serial.print('\t'); |
| 103 | + Serial.print(y); |
| 104 | + Serial.print('\t'); |
| 105 | + Serial.println(z); |
| 106 | + } |
| 107 | +} |
| 108 | +``` |
| 109 | + |
| 110 | +### Full Sketch |
| 111 | + |
| 112 | +Now to put it all together where the image will change depending on how we rotate the board and shield: |
| 113 | + |
| 114 | +```arduino |
| 115 | +#include "Arduino_BMI270_BMM150.h" |
| 116 | +#include "Arduino_H7_Video.h" |
| 117 | +#include "lvgl.h" |
| 118 | +
|
| 119 | +Arduino_H7_Video Display(800, 480, GigaDisplayShield); /* Arduino_H7_Video Display(1024, 768, USBCVideo); */ |
| 120 | +
|
| 121 | +BoschSensorClass imu(Wire1); |
| 122 | +
|
| 123 | +LV_IMG_DECLARE(img_arduinologo); |
| 124 | +lv_obj_t * img; |
| 125 | +
|
| 126 | +void setup() { |
| 127 | + Serial.begin(115200); |
| 128 | + |
| 129 | + Display.begin(); |
| 130 | + imu.begin(); |
| 131 | +
|
| 132 | + img = lv_img_create(lv_scr_act()); |
| 133 | + lv_img_set_src(img, &img_arduinologo); |
| 134 | + lv_obj_align(img, LV_ALIGN_CENTER, 0, 0); |
| 135 | + lv_img_set_pivot(img, (img_arduinologo.header.w)/2, (img_arduinologo.header.h)/2); /* Rotate around the center of the image */ |
| 136 | +} |
| 137 | +
|
| 138 | +uint8_t rotation = 0; |
| 139 | +
|
| 140 | +void loop() { |
| 141 | + float x, y, z; |
| 142 | + if (imu.accelerationAvailable()) { |
| 143 | + imu.readAcceleration(x, y, z); |
| 144 | + if ( z < 0.8 && z > -0.8) { |
| 145 | + if (x < -0.8) { |
| 146 | + rotation = 0; |
| 147 | + } else if (x > 0.8) { |
| 148 | + rotation = 2; |
| 149 | + } else if (y < -0.8) { |
| 150 | + rotation = 1; |
| 151 | + } else if (y > 0.8) { |
| 152 | + rotation = 3; |
| 153 | + } |
| 154 | + int16_t rot_angle = 900 - atan(x / y) * 180.0 / M_PI * 10; |
| 155 | + lv_img_set_angle(img, rot_angle); |
| 156 | + } |
| 157 | + } |
| 158 | + lv_timer_handler(); |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +### Using Another Image |
| 163 | + |
| 164 | +Any image could be the sketch. This tutorial and the example uses an image of the Arduino logo. Alternatively, any raw RGB565 image can be used. If you have an image you want to use, you can use this [online image converter](https://lvgl.io/tools/imageconverter), or any other software that lets you convert an image to a raw RGB565 image. This website will output in the Binary RGB565 format. For further instructions on how to display your own image, have a look at our [Text and Image tutorial](text-and-image). |
| 165 | + |
| 166 | +## Testing It Out |
| 167 | + |
| 168 | +Now try rotating your device to see if the image behaves correctly. If the image does not rotate correctly have another look at the values you entered into the previous sketch. It might help to try and run the simple IMU readings printer sketch to take a quick look at the IMU values in the serial monitor. This will help you figure out what values should be considered when the device is being moved. |
| 169 | + |
| 170 | +[Gif of the orientation sketch running on the screen]() |
| 171 | + |
| 172 | +## Conclusion |
| 173 | + |
| 174 | +Now you know how to use the GIGA Display Shield's IMU sensor to gather readings for device orientation, and how to use these readings to make an image on the GIGA Display Shield maintain the correct orientation depending on what way it is facing. |
0 commit comments