Игра EuroTruckSimulator 2 — авто-симулятор вождения большегрузных грузовиков. В сообществе этой игры, периодически встречаются «маньяки», которым так и хочется приблизить данный симулятор еще больше к реальности и они начинают изобретать! Благо разработчики игры, фирма SCS, выпустила SDK телеметрии, благодаря чему можно получить любые данные телеметрии из игрового процесса.
Один такой энтузиаст Silas Parker написал библиотеку ets2_dashboard, она работает как плагин для игры EuroTruckSimulator 2 и передает на серийный COM порт необходимые параметры.
В свою очередь, приемником на COM порту выступает плата Arduino UNO, которая обрабатывает поступающие сигналы и распределяет по своим портам.
Для правильного функционирования Arduino, необходимо ее прошить, заранее подготовленной прошивкой. Эту прошивку можно найти в ets2_dashboard. В данной прошивке сигналы на разные стрелочные индикаторы, передаются на серво приводы.
Все бы хорошо, но знакомые ребята, которые начали собирать свои «симуляторы», имели приборные панели с аналоговыми приводами приборов. Собственно по этому и возникла необходимость видоизменить саму прошивку для Arduino так, чтоб на порты выдавался сигнал не для серво привода, а аналоговый ШИМ.
Для того чтоб не переписывать библиотеку, решено было от «мапить» данные для серво приводов, под аналоговый ШИМ.
Так как я в первые столкнулся с Arduino, было немного не просто сразу понять, что к чему, но благо на русскоязычном сайте Arduino есть очень хорошая документация по программированию этих плат.
После недолгих разбирательств, получилась вот такая вот прошивка:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
/* Copyright (c) 2013, Silas Parker Modification for analog drives. Made by labor24krs All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The name of Silas Parker may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <liquidcrystal .h> // PWM~ const int SPEED_PIN = 3; const int RPM_PIN = 5; const int BREAK_AIR_PIN = 6; const int FUEL_PIN = 9; const int OIL_PIN = 10; const int WATER_PIN = 11; // Digital const int LEFT_INDICATOR = A2; const int RIGHT_INDICATOR = A3; const int PARKING_BREAK = A4; const int FUEL_WARNING = A5; // variable declaration int pwcMin = 0; int pwcMax = 255; #define PACKET_SYNC 0xFF #define PACKET_VER 2 int serial_byte; LiquidCrystal lcd(12, 8, 7, 4, 2, 1); void setup() { Serial.begin(115200); lcd.begin(16, 2); lcd.print("Self Test"); analogWrite(SPEED_PIN, pwcMax); analogWrite(RPM_PIN, pwcMax); analogWrite(BREAK_AIR_PIN, pwcMax); analogWrite(FUEL_PIN, pwcMax); analogWrite(OIL_PIN, pwcMax); analogWrite(WATER_PIN, pwcMax); // Initialise LEDs pinMode(LEFT_INDICATOR, OUTPUT); pinMode(RIGHT_INDICATOR, OUTPUT); pinMode(PARKING_BREAK, OUTPUT); pinMode(FUEL_WARNING, OUTPUT); digitalWrite(LEFT_INDICATOR, 0); digitalWrite(RIGHT_INDICATOR, 0); digitalWrite(PARKING_BREAK, 0); digitalWrite(FUEL_WARNING, 0); delay(500); analogWrite(SPEED_PIN, pwcMin); analogWrite(RPM_PIN, pwcMin); analogWrite(BREAK_AIR_PIN, pwcMin); analogWrite(FUEL_PIN, pwcMin); analogWrite(OIL_PIN, pwcMin); analogWrite(WATER_PIN, pwcMin); digitalWrite(LEFT_INDICATOR, 1); digitalWrite(RIGHT_INDICATOR, 1); digitalWrite(PARKING_BREAK, 1); digitalWrite(FUEL_WARNING, 1); delay(500); analogWrite(SPEED_PIN, pwcMax); analogWrite(RPM_PIN, pwcMax); analogWrite(BREAK_AIR_PIN, pwcMax); analogWrite(FUEL_PIN, pwcMax); analogWrite(OIL_PIN, pwcMax); analogWrite(WATER_PIN, pwcMax); digitalWrite(LEFT_INDICATOR, 0); digitalWrite(RIGHT_INDICATOR, 0); digitalWrite(PARKING_BREAK, 0); digitalWrite(FUEL_WARNING, 0); lcd.clear(); lcd.print("Wait"); // Wait a second to ensure serial data is not from re-programming delay(1000); lcd.clear(); lcd.print("Ready"); } void read_serial_byte_set_pwm(int pin) { serial_byte = Serial.read(); int pwc = 0; // period working cycle, transfer values from the servo in pwm pwc = map(serial_byte, 0, 180, 0, 255); analogWrite(pin, pwc); } void skip_serial_byte() { (void)Serial.read(); } void digitalWriteFromBit(int port, int value, int shift) { digitalWrite(port, (value >> shift) & 0x01); } void loop() { if (Serial.available() < 16) return; serial_byte = Serial.read(); if (serial_byte != PACKET_SYNC) return; serial_byte = Serial.read(); if (serial_byte != PACKET_VER) { lcd.clear(); lcd.print("PROTOCOL VERSION ERROR"); return; } // For PWM // Changing the order of transfer of functions implies the wrong job read_serial_byte_set_pwm(SPEED_PIN); // Speed read_serial_byte_set_pwm(RPM_PIN); // RPM read_serial_byte_set_pwm(BREAK_AIR_PIN); // Brake air pressure skip_serial_byte(); // Brake temperature read_serial_byte_set_pwm(FUEL_PIN); // Fuel ratio read_serial_byte_set_pwm(OIL_PIN); // Oil pressure skip_serial_byte(); // Oil temperature read_serial_byte_set_pwm(WATER_PIN); // Water temperature skip_serial_byte(); // Battery voltage // Truck lights byte serial_byte = Serial.read(); digitalWriteFromBit(LEFT_INDICATOR, serial_byte, 5); digitalWriteFromBit(RIGHT_INDICATOR, serial_byte, 4); // Warning lights bytes serial_byte = Serial.read(); digitalWriteFromBit(PARKING_BREAK, serial_byte, 7); digitalWriteFromBit(FUEL_WARNING, serial_byte, 3); // Enabled flags serial_byte = Serial.read(); // Text length int text_len = Serial.read(); // Followed by text if (0 < text_len && text_len < 127) { lcd.clear(); for (int i = 0; i < text_len; ++i) { while (Serial.available() == 0) // Wait for data if slow { delay(2); } serial_byte = Serial.read(); if (serial_byte < 0 && serial_byte > 127) return; if (serial_byte == '\n') lcd.setCursor(0, 1); else lcd.print(char(serial_byte)); // delay(2); } } } //</liquidcrystal> |
В этой прошивке данные выводятся на следующие PWM~ порты:
Параметр | Порт Арудино |
Скорость движения | Порт 3 |
Обороты двигателя | Порт 5 |
Давление тормозной системы | Порт 6 |
Запас топлива | Порт 9 |
Давление масла | Порт 10 |
Температура жидкости | Порт 11 |
Внимание!
На большинстве плат Arduino (на базе микроконтроллера ATmega168 или ATmega328) ШИМ поддерживают порты 3, 5, 6, 9, 10 и 11, на плате Arduino Mega порты с 2 по 13. На более ранних версиях плат Arduino analogWrite() работал только на портах 9, 10 и 11.[примечания analogWrite()]
Добавить комментарий