T.interface - Arduino Dan Gyroscope
T.interface - Arduino Dan Gyroscope
DISUSUN OLEH :
NIM : 2022204010038
1. Tujuan
Tujuan dari praktikum ini adalah untuk mempelajari penggunaan dan integrasi sensor
gyroscope MPU-6050 dengan layar OLED menggunakan platform Arduino.
3. Prosedur
1. Setup Hardware:
o Hubungkan sensor MPU-6050 ke Arduino Uno:
VCC ke 3.3V
GND ke GND
SCL ke pin A5 (SCL)
SDA ke pin A4 (SDA)
o Hubungkan layar OLED ke Arduino Uno:
VCC ke 3.3V
GND ke GND
SCL ke pin A5 (SCL)
SDA ke pin A4 (SDA)
2. Menulis Kode Arduino:
o Buka Arduino IDE dan buat program baru.
o Instal library Adafruit MPU6050, Adafruit GFX, dan Adafruit SSD1306 dari
Library Manager.
o Tulis kode untuk membaca data dari sensor MPU-6050 dan menampilkannya
di layar OLED.
o Membuat program:
3. #include <Wire.h>
4. #include <Adafruit_SSD1306.h>
5. #include <Adafruit_GFX.h>
6. #include <Adafruit_NeoPixel.h>
7.
8. Adafruit_SSD1306 display( 128, 64); // 128 pixels width, 64 pixels
height
9.
10. #define LED_PIN 6
11. #define LED_COUNT 1
12. Adafruit_NeoPixel neoPixel( LED_COUNT, LED_PIN, NEO_GRB +
NEO_KHZ800);
13.
14. const int mpuAddress = 0x68; // I2C address of the
MPU-6050
15.
16. float xByGyro, yByGyro, zByGyro; // Global variables for
the rotation by gyro
17.
18. // Set the origin in the middle of the display
19. const int xOrigin = 64;
20. const int yOrigin = 32;
21.
22. const float viewDistance = 150.0; // higher for less
perspective, lower for more.
23.
24. // Vertices for a cube
25. // A cube has 8 corners and each coordinate has x,y,z values.
26. #define NUM_VERTICES 8
27. const int cube_vertex[NUM_VERTICES][3] =
28. {
29. { -20, -20, 20 }, // x, y, z
30. { 20, -20, 20 },
31. { 20, 20, 20 },
32. { -20, 20, 20 },
33. { -20, -20, -20 },
34. { 20, -20, -20 },
35. { 20, 20, -20 },
36. { -20, 20, -20 }
37. };
38.
39. // The wirefram is to display the lines on the OLED display
40. // It contains the corners of the shape in 2D coordinates
41. int wireframe[NUM_VERTICES][2];
42.
43.
44. void setup()
45. {
46. Serial.begin( 115200);
47.
48. Wire.begin();
49.
50. // Initialize the OLED display and test if it is connected.
51. if( !display.begin( SSD1306_SWITCHCAPVCC, 0x3C))
52. {
53. Serial.println(F( "SSD1306 allocation failed"));
54. for(;;); // halt the
sketch if error encountered
55. }
56.
57. // Initialize the MPU-6050 and test if it is connected.
58. Wire.beginTransmission( mpuAddress);
59. Wire.write( 0x6B); // PWR_MGMT_1
register
60. Wire.write( 0); // set to zero
(wakes up the MPU-6050)
61. auto error = Wire.endTransmission();
62. if( error != 0)
63. {
64. Serial.println(F( "Error, MPU-6050 not found"));
65. for(;;); // halt the
sketch if error encountered
66. }
67.
68. // Initialize the NeoPixel
69. neoPixel.begin();
70. }
71.
72.
73. void loop()
74. {
75. Wire.beginTransmission( mpuAddress);
76. Wire.write( 0x3B); // Starting with
register 0x3B (ACCEL_XOUT_H)
77. Wire.endTransmission( false); // No stop condition for
a repeated start
78.
79. // The MPU-6050 has the values as signed 16-bit integers.
80. // There are 7 values in 14 registers.
81. int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
82.
83. Wire.requestFrom( mpuAddress, 14); // request a total of 14
bytes
84. AcX = Wire.read()<<8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) &
0x3C (ACCEL_XOUT_L)
85. AcY = Wire.read()<<8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) &
0x3E (ACCEL_YOUT_L)
86. AcZ = Wire.read()<<8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) &
0x40 (ACCEL_ZOUT_L)
87. Tmp = Wire.read()<<8 | Wire.read(); // 0x41 (TEMP_OUT_H) &
0x42 (TEMP_OUT_L)
88. GyX = Wire.read()<<8 | Wire.read(); // 0x43 (GYRO_XOUT_H) &
0x44 (GYRO_XOUT_L)
89. GyY = Wire.read()<<8 | Wire.read(); // 0x45 (GYRO_YOUT_H) &
0x46 (GYRO_YOUT_L)
90. GyZ = Wire.read()<<8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) &
0x48 (GYRO_ZOUT_L)
91.
92. // The acceleration is directly mapped into the angles.
93. // That is rather artificial.
94. // The combined gravity could be used for an angle, while
ignoring the strength.
95. //
96. // The gyro sets the rotation speed.
97. // The angle created by the rotation speed is added to angle
by the accelerometer.
98. //
99. // The conversion from the sensor values to the rotation is
just a value
100. // that makes it look good on the display.
101.
102. float xByAccel = (float) AcX * 0.0001; // static angle
by accelerometer
103. float yByAccel = (float) AcY * 0.0001;
104. float zByAccel = (float) AcZ * 0.0001;
105.
106. xByGyro += (float) GyX * 0.00001; // moving angle
by gyro
107. yByGyro += (float) GyY * 0.00001;
108. zByGyro += (float) GyZ * 0.00001;
109.
110. float x = xByAccel + xByGyro; // combine both
angles
111. float y = yByAccel + yByGyro;
112. float z = zByAccel + zByGyro;
113.
114. // Keep the radians in range (although the cos/sin functions
accept every value)
115. if( x < 0.0)
116. x += 2.0 * M_PI;
117. else if( x > 2.0 * M_PI)
118. x -= 2.0 * M_PI;
119. if( y < 0.0)
120. y += 2.0 * M_PI;
121. else if( y > 2.0 * M_PI)
122. y -= 2.0 * M_PI;
123. if( z < 0.0)
124. z += 2.0 * M_PI;
125. else if( z > 2.0 * M_PI)
126. z -= 2.0 * M_PI;
127.
128. // Draw 3D picture
129. for (int i = 0; i < NUM_VERTICES; i++)
130. {
131. // Rotate Y
132. float rotx = cube_vertex[i][2] * sin(y) + cube_vertex[i][0]
* cos(y);
133. float roty = cube_vertex[i][1];
134. float rotz = cube_vertex[i][2] * cos(y) - cube_vertex[i][0]
* sin(y);
135.
136. // Rotate X
137. float rotxx = rotx;
138. float rotyy = roty * cos(x) - rotz * sin(x);
139. float rotzz = roty * sin(x) + rotz * cos(x);
140.
141. // Rotate Z
142. float rotxxx = rotxx * cos(z) - rotyy * sin(z);
143. float rotyyy = rotxx * sin(z) + rotyy * cos(z);
144. float rotzzz = rotzz;
145.
146. // Add depth perspective
147. rotxxx *= viewDistance / (viewDistance + rotzzz);
148. rotyyy *= viewDistance / (viewDistance + rotzzz);
149.
150. // Bring to middle of screen
151. rotxxx += (float) xOrigin;
152. rotyyy += (float) yOrigin;
153.
154. // Store new vertices values for wireframe drawing
155. wireframe[i][0] = (int) rotxxx;
156. wireframe[i][1] = (int) rotyyy;
157. wireframe[i][2] = (int) rotzzz;
158. }
159. draw_wireframe();
160.
161.
162. // Set the color of the NeoPixel according to the temperature
163. // Temperature by the MPU-6050 is -40 to 85.
164. // According to the datasheet:
165. // Temperature in Celsius = (raw_value / 340) + 36.53
166. // The Hue range for the NeoPixel is the full uint16_t range.
167. float Celsius = ((float) Tmp / 340.00) + 36.53;
168. float hue = (Celsius + 40.0) / 125.0 * 65535.0;
169. uint32_t rgbcolor = neoPixel.ColorHSV( (uint16_t) hue);
170. neoPixel.setPixelColor( 0, rgbcolor);
171. neoPixel.show(); // update new values
to NeoPixel
172. }
173.
174.
175. void draw_wireframe(void)
176. {
177. // Start with a empty buffer
178. display.clearDisplay();
179.
180. // A cube has 8 points and 12 sides.
181. // The wireframe contains the 8 points, and the 12 lines are
drawn here.
182. display.drawLine( wireframe[0][0], wireframe[0][1],
wireframe[1][0], wireframe[1][1], SSD1306_WHITE);
183. display.drawLine( wireframe[1][0], wireframe[1][1],
wireframe[2][0], wireframe[2][1], SSD1306_WHITE);
184. display.drawLine( wireframe[2][0], wireframe[2][1],
wireframe[3][0], wireframe[3][1], SSD1306_WHITE);
185. display.drawLine( wireframe[3][0], wireframe[3][1],
wireframe[0][0], wireframe[0][1], SSD1306_WHITE);
186.
187. display.drawLine( wireframe[4][0], wireframe[4][1],
wireframe[5][0], wireframe[5][1], SSD1306_WHITE);
188. display.drawLine( wireframe[5][0], wireframe[5][1],
wireframe[6][0], wireframe[6][1], SSD1306_WHITE);
189. display.drawLine( wireframe[6][0], wireframe[6][1],
wireframe[7][0], wireframe[7][1], SSD1306_WHITE);
190. display.drawLine( wireframe[7][0], wireframe[7][1],
wireframe[4][0], wireframe[4][1], SSD1306_WHITE);
191.
192. display.drawLine( wireframe[0][0], wireframe[0][1],
wireframe[4][0], wireframe[4][1], SSD1306_WHITE);
193. display.drawLine( wireframe[1][0], wireframe[1][1],
wireframe[5][0], wireframe[5][1], SSD1306_WHITE);
194. display.drawLine( wireframe[2][0], wireframe[2][1],
wireframe[6][0], wireframe[6][1], SSD1306_WHITE);
195. display.drawLine( wireframe[3][0], wireframe[3][1],
wireframe[7][0], wireframe[7][1], SSD1306_WHITE);
196.
197. // Extra cross face on one side
198. display.drawLine( wireframe[1][0], wireframe[1][1],
wireframe[3][0], wireframe[3][1], SSD1306_WHITE);
199. display.drawLine( wireframe[0][0], wireframe[0][1],
wireframe[2][0], wireframe[2][1], SSD1306_WHITE);
200.
201. // Write the new picture to the display
202. display.display();
203. }
3. Menjalankan Program:
4. Hasil Pengamatan
Membuat Rangkaian:
HASIL SIMULASI:
ANALISA:
Analisis Program: Menampilkan Volume, Bass, dan Treble pada Sound dengan Rotary
Encoder dan OLED
Fungsi `updateValue()` digunakan untuk mengupdate nilai volume, bass, dan treble. Fungsi
ini menggunakan switch statement untuk mengupdate nilai berdasarkan mode yang sedang
digunakan. Nilai yang diupdate adalah `volume`, `bass`, dan `treble`.
Fungsi `setup()` digunakan untuk menginisialisasi perangkat, termasuk OLED display dan
rotary encoder. Fungsi `loop()` digunakan untuk mengontrol perangkat dan mengupdate
display berdasarkan input dari rotary encoder.
### 6. Analisis
1. **Rotary Encoder**: Program ini menggunakan rotary encoder untuk mengontrol volume,
bass, dan treble. Rotary encoder digunakan untuk mengupdate nilai volume, bass, dan treble
berdasarkan posisi dan arah putar encoder.
3. **Mode**: Program ini memiliki tiga mode yang tersedia, yaitu `SET_VOLUME`,
`SET_BASS`, dan `SET_TREBLE`. Mode ini digunakan untuk mengatur nilai volume, bass,
dan treble.
4. **Input dan Output**: Program ini memiliki input dari rotary encoder dan output pada
OLED display. Input dari rotary encoder digunakan untuk mengupdate nilai volume, bass,
dan treble, sedangkan output pada OLED display digunakan untuk menampilkan nilai
volume, bass, dan treble.
### 7. Kesimpulan
Program ini digunakan untuk mengontrol volume, bass, dan treble pada sound system
menggunakan rotary encoder dan OLED display. Program ini memiliki struktur yang jelas
dan menggunakan beberapa fungsi untuk mengupdate nilai volume, bass, dan treble
berdasarkan input dari rotary encoder dan menampilkan hasilnya pada OLED display.