Этот проект представляет собой создание простого инклинометра (угломера) на Ардуино с автоматическим измерением углов наклона в разных плоскостях.
Этот инклинометр можно поворачивать в любом положении, сохраняя читаемость цифр даже перевернув плату вверх ногами. Устройство контролируется Arduino 101 с помощью акселерометров для считывания угла наклона осей X-Y.
Кроме того, есть функция, показывающая температуру окружающей среды в градусах Цельсия или градусах Фаренгейта. Сборка очень проста, и надеемся, вам понравится.
Шаг 1: Список комплектующих
Arduino 101: эта версия Arduino больше не производится, несмотря на наличие интересных функций, таких как датчик температуры, 6-осевой акселерометр, гироскоп, датчик температуры и bluetooth на борту.
Для этого проекта очень полезно избегать внешнего MPU.
Многофункциональный щит (MFD): MFD может упростить и ускорить разработку прототипа. Основные возможности:
- 4-значный 7-сегментный светодиодный дисплейный модуль, управляемый двумя серийными 74HC595
- 4 светодиода для поверхностного монтажа в параллельной конфигурации
- 10K регулируемый прецизионный потенциометр
- 3 независимых кнопки
- Пьезо-зуммер
- Интерфейс датчика DS18B20
- Интерфейс датчика температуры LM35
- Интерфейс инфракрасного приемника
- Контакты последовательного интерфейса для удобного подключения к последовательным модулям, таким как Bluetooth (беспроводной интерфейс), голосовый модуль, модуль распознавания голоса и т.д.
Шаг 2: Сборка
Сборка очень проста и нет необходимости в каких-либо схемах.
Просто вставьте многофункциональный щит в Arduino, заботясь о контактах, чтобы избежать каких-либо повреждений во время вставки.
Шаг 3: Настройка
Для настройки инклинометра Ардуино есть 3 кнопки:
Левая кнопка: выберите рабочий режим.
a) Автоматическая ось. В этом режиме ось (X или Y) для измерения степени наклона автоматически выбирается внутренним гироскопом.
б) Х-ось. Показать только углы оси X.
c) Y-ось. Показать только углы оси Y.
d) Температура - показать температуру окружающей среды в градусах Цельсия или Фаренгейта.
Центральная кнопка: задайте нулевой градус по оси X и Y. Когда выбран температурный режим, эта кнопка устанавливает температурный масштаб (ºC или ºF).
Правая кнопка: Сбросьте оси до исходных углов.
Шаг 4: Функция передачи
Основными функциями кода являются:
- Чтение углов наклона акселерометров.
- Расчет передаточной функции эффекта перевернутой стороны для 7-сегментного светодиодного дисплея.
С углами можно определить пространственное положение устройства, чтобы решить, что показывать (картинка сверху):
- Вид спереди - Инклинометр в первоначальном положении
- Вид спереди - Инклинометр вверх дном
Функция передачи для отображения 7-сегмент (от А до F) работает следующим образом:
От A до D, от B до E, от C до F, от D до A, от E до B, от F до C, от G до G
Для завершения эффекта перевернутости необходимо инвертировать последовательность символов на дисплее:
От: 1, 2, 3, 4
До: 4, 3, 2, 1
Шаг 5: Код
Приложенный ниже код должен применяться только к Arduino 101.
Для другой версии Arduino требуется некоторое обновление кода, а также использование внешнего MPU-6050 для акселерометров.
#define SDA_PORT PORTD #define SDA_PIN 5 #define SCL_PORT PORTD #define SCL_PIN 6 #include <CurieTimerOne.h> #include <CurieIMU.h> // Module connection pins (Digital Pins) #define LATCH_PIN 4 // Arduino 101 conection on Pin #4 = Latch of Display Module #define CLK_PIN 7 // Arduino 101 conection on Pin #7 = Clock of Display Module #define DATA_PIN 8 // Arduino 101 conection on Pin #8 = Data of Display Module #define BTN_1_PIN A1 #define BTN_2_PIN A2 #define BTN_3_PIN A3 // Front: Upside Down: // A D // ---- ---- // F | | B C | | E // -G - -G - // E | | C B | | F // ---- ---- // D A // // Chars Code {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, = , ||, º, C, F} byte N[] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6, 0x28, 0x12, 0xC6, 0x9C, 0x8E}; int delayRefresh; byte view; unsigned long ti; float AcX, AcY, AcZ, gX, gY, gZ; int uniAngle, dezAngle; int axis, angle, angleX, angleRefX, angleY, angleRefY, temp; boolean axisX, axisY, tempStatus, tCelsius; void setup() { pinMode(LATCH_PIN, OUTPUT); pinMode(CLK_PIN, OUTPUT); pinMode(DATA_PIN, OUTPUT); pinMode(BTN_1_PIN, INPUT); pinMode(BTN_2_PIN, INPUT); pinMode(BTN_3_PIN, INPUT); pinMode(13, OUTPUT); digitalWrite(13, HIGH); CurieTimerOne.start(180000, kbdRead); CurieIMU.begin(); // Set the accelerometer range to 2G CurieIMU.setAccelerometerRange(2); // Set gyro range to 250º/second CurieIMU.setGyroRange(250); view = 0; // Front View (regular view as default) axisX = true; axisY = false; angleRefX = 0; angleRefY = 0; axis = 0; tempStatus = false; tCelsius = true; } void loop() { delayRefresh = 70; CurieIMU.readAccelerometerScaled(AcX, AcY, AcZ); // Read Accelerometers (G = m/s/s) CurieIMU.readGyroScaled(gX, gY, gZ); // Read Gyro (º/s) temp = (CurieIMU.readTemperature() / 512) + 13; // Read the temperature in Celsius degrees (ºC) if (AcX < 0) { view = 0; // Front View (regular view) } if (AcX > 0) { view = 1; // Front View (Upside Down) } angleX = atan(AcX / AcZ) * 180 / PI - angleRefX; angleY = atan(AcY / AcZ) * 180 / PI - angleRefY; if ((abs(gY) > 5) && (abs(gX) < 2) && (axis == 0)) { axisX = true; axisY = false; } if ((abs(gX) > 5) && (abs(gY) < 2) && (axis == 0)) { axisX = false; axisY = true; } if (axisX) { angle = angleX; } if (axisY) { angle = angleY; } uniAngle = abs(int(angle)) % 10; dezAngle = abs(int(angle)) / 10; // Display the Angle (-XXº) or Temperature (ºC / ºF) if (tempStatus == false) { ti = millis(); // Initial time for blinking dot while ((millis() - ti) < delayRefresh) { // Timer in miliseconds to refresh the display if (view == 0) { // Front View mode (1) if (angle < 0) { displayChars(2, view, 0); // Display Minus Signal "-" at Digi 0 } displayChars(N[abs(dezAngle)], view, 1); // Display Digit 1 displayChars(N[abs(uniAngle)], view, 2); // Display Digit 2 if (axisY) { displayChars(N[10], view, 3); // Display Degree Symbol "||" for Y-axis } if (axisX) { displayChars(N[11], view, 3); // Display Degree Symbol "=" for X-axis } } if (view == 1) { // Front Upside Down mode (2) if (angle < 0) { displayChars(2, view, 3); // Display Minus Signal "-" at Digit 3 } displayChars(N[dezAngle], view, 2); // Display Digit 2 displayChars(N[uniAngle], view, 1); // Display Digit 1 if (axisY) { displayChars(N[10], view, 0); // Display Symbol "||" for Y-axis } if (axisX) { displayChars(N[11], view, 0); // Display Symbol "=" for X-axis } } } } if (tempStatus == true) { if (!tCelsius) { // Temperature conversion - Celsius to Fahrenheit temp = temp * 9 / 5 + 32; } ti = millis(); // Initial time for blinking dot while ((millis() - ti) < delayRefresh) { // Timer in miliseconds to refresh the display if (view == 0) { // Front View mode (1) displayChars(N[temp / 10], view, 0); // Display Digit 0 displayChars(N[temp % 10], view, 1); // Display Digit 1 displayChars(N[12], view, 2); // Display Digit 2 - Symbol "º" if (tCelsius) { displayChars(N[13], view, 3); // Display Degree Symbol "C" } else { displayChars(N[14], view, 3); // Display Degree Symbol "F" } } if (view == 1) { // Front View mode (1) displayChars(N[temp / 10], view, 3); // Display Digit 0 displayChars(N[temp % 10], view, 2); // Display Digit 1 displayChars(N[12], view, 1); // Display Digit 2 - Symbol "º" if (tCelsius) { displayChars(N[13], view, 0); // Display Degree Symbol "C" } else { displayChars(N[14], view, 0); // Display Degree Symbol "F" } } } displayChars(0, 1, 0); // Clear Digit 0 displayChars(0, 1, 1); // Clear Digit 1 displayChars(0, 1, 2); // Clear Digit 2 displayChars(0, 1, 3); // Clear Digit 3 } } void displayChars(byte num, byte statusM, byte disp) { // Chars Display Routine if (statusM == 1) { // Front Upside Down num = ((num >> 2) << 5) | ((num >> 5 ) << 2) | (num & 2); } digitalWrite(LATCH_PIN, LOW); shiftOut(DATA_PIN, CLK_PIN, LSBFIRST, ~num); // Display number shiftOut(DATA_PIN, CLK_PIN, LSBFIRST, 128 >> disp); // Set Digit (0-1-2-3) digitalWrite(LATCH_PIN, HIGH); } void kbdRead() { // Push Buttons Reading if (!digitalRead(BTN_1_PIN)) { // Set mode axis = (axis + 1) % 4; if (axis == 0) { // Set mode "auto view" (X & Y axis) tempStatus = false; } if (axis == 1) { // Set mode X-axis only axisX = true; axisY = false; } if (axis == 2) { // Set mode Y-axis only axisX = false; axisY = true; } if (axis == 3) { // Set Temperature mode tempStatus = true; } } if (!digitalRead(BTN_2_PIN) && !tempStatus) { // Set reference for X & Y axis angleRefX = angleX; angleRefY = angleY; } if (!digitalRead(BTN_2_PIN) && tempStatus) { // Set temperature scale (ºC or ºF) in temperature mode tCelsius = !tCelsius; } if (!digitalRead(BTN_3_PIN) && !tempStatus) { // Reset X & Y axis to original values/reference angleRefX = 0; angleRefY = 0; } }
Как это работает можно посмотреть в итоговом видео.
На этом всё. Хороших вам проектов.