arduino:pinball
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
arduino:pinball [2014/11/19 19:49] – angelegt ros | arduino:pinball [2014/12/03 07:48] (aktuell) – gelöscht ros | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== Punkteanzeige für Flipperautomat ====== | ||
- | [[arduino: | ||
- | |||
- | Dieses Programm steuert ein Anzeigemodul für einen Flipperautomaten. Das Anzeigemodul besteht aus fünf 7-Segmentanzeigen, | ||
- | |||
- | Ausserdem können auf einer SD-Karte gespeicherte Audiodateien abgespielt werden. | ||
- | |||
- | Die Aktionen werden durch Aktivieren verschiedener Eingänge (Inputs) ausgelöst. Die Aktionen können für jeden Eingang in einer Datei auf der SD-Karte konfiguriert werden. | ||
- | |||
- | <code c++> | ||
- | #include " | ||
- | #include < | ||
- | #include " | ||
- | #include " | ||
- | |||
- | // -------------------------------------------------------------------------------------------------- | ||
- | // Parameters | ||
- | // -------------------------------------------------------------------------------------------------- | ||
- | |||
- | #define STEP 50 | ||
- | |||
- | // -------------------------------------------------------------------------------------------------- | ||
- | // Pins | ||
- | // -------------------------------------------------------------------------------------------------- | ||
- | |||
- | #define DISPLAY_DATA_PIN 7 | ||
- | #define DISPLAY_SHIFT_CLOCK_PIN 8 | ||
- | #define DISPLAY_STORAGE_CLOCK_PIN 3 | ||
- | #define LED_DATA_PIN 4 | ||
- | #define LED_SHIFT_CLOCK_PIN 5 | ||
- | #define LED_STORAGE_CLOCK_PIN 6 | ||
- | #define SD_CARD_CHIP_SELECT_PIN 10 | ||
- | #define SPEAKER_PIN 9 | ||
- | |||
- | const byte INPUT_PINS[] = { A1, A2, A0, A3, 0, A4, 1, A5, 2 }; | ||
- | const byte INPUT_COUNT = sizeof(INPUT_PINS) / sizeof(byte); | ||
- | |||
- | // -------------------------------------------------------------------------------------------------- | ||
- | // 7-segment display | ||
- | // -------------------------------------------------------------------------------------------------- | ||
- | |||
- | const int DISPLAY_DIGIT_COUNT = 5; | ||
- | |||
- | const int DISPLAY_DIGIT[] = { | ||
- | // | ||
- | B11111010, // 0 | ||
- | B11000000, // 1 | ||
- | B01110110, // 2 | ||
- | B11110100, // 3 | ||
- | B11001100, // 4 | ||
- | B10111100, // 5 | ||
- | B10111110, // 6 | ||
- | B11100000, // 7 | ||
- | B11111110, // 8 | ||
- | B11111100 | ||
- | }; | ||
- | |||
- | int getDigit(int digit) { | ||
- | return DISPLAY_DIGIT[digit]; | ||
- | } | ||
- | |||
- | // | ||
- | #define DISPLAY_E B00111110 | ||
- | #define DISPLAY_R B00000110 | ||
- | #define DISPLAY_O B10010110 | ||
- | |||
- | const int DISPLAY_ERROR_MESSAGE[] = { DISPLAY_R, DISPLAY_O, DISPLAY_R, DISPLAY_R, DISPLAY_E }; | ||
- | |||
- | class PinballDisplay { | ||
- | boolean _error; // display ' | ||
- | unsigned long _score; | ||
- | long _scoreToAdd; | ||
- | |||
- | void update() { | ||
- | digitalWrite(DISPLAY_STORAGE_CLOCK_PIN, | ||
- | nop(); | ||
- | if (_error) { | ||
- | for (int i = 0; i < DISPLAY_DIGIT_COUNT; | ||
- | shiftOut(DISPLAY_DATA_PIN, | ||
- | nop(); | ||
- | } | ||
- | } | ||
- | else { | ||
- | long d = 1; | ||
- | for (int i = 0; i < DISPLAY_DIGIT_COUNT; | ||
- | int digit = getDigit((_score / d) % 10); | ||
- | shiftOut(DISPLAY_DATA_PIN, | ||
- | delay(10); | ||
- | d *= 10; | ||
- | } | ||
- | } | ||
- | delay(10); | ||
- | digitalWrite(DISPLAY_STORAGE_CLOCK_PIN, | ||
- | delay(10); | ||
- | } | ||
- | |||
- | public: | ||
- | PinballDisplay() : | ||
- | _error(false), | ||
- | _score(0), | ||
- | _scoreToAdd(0) | ||
- | { | ||
- | pinMode(DISPLAY_DATA_PIN, | ||
- | pinMode(DISPLAY_SHIFT_CLOCK_PIN, | ||
- | pinMode(DISPLAY_STORAGE_CLOCK_PIN, | ||
- | update(); | ||
- | } | ||
- | |||
- | void addScore(long amount) { | ||
- | _score += amount; | ||
- | update(); | ||
- | } | ||
- | |||
- | void addScoreSlow(long amount) { | ||
- | _scoreToAdd += amount; | ||
- | update(); | ||
- | } | ||
- | |||
- | void loop() { | ||
- | if (_scoreToAdd > 0) { | ||
- | _score = _score + STEP; | ||
- | _scoreToAdd = _scoreToAdd - STEP; | ||
- | update(); | ||
- | } | ||
- | } | ||
- | |||
- | void setError() { | ||
- | _error = true; | ||
- | } | ||
- | | ||
- | void setScore(unsigned int newScore) { | ||
- | _score = newScore; | ||
- | _error = false; | ||
- | update(); | ||
- | } | ||
- | }; | ||
- | |||
- | PinballDisplay* display; | ||
- | |||
- | // -------------------------------------------------------------------------------------------------- | ||
- | // LED Animation | ||
- | // -------------------------------------------------------------------------------------------------- | ||
- | |||
- | const int LED_MAP[] = { | ||
- | B10000000, // Output Pin 17 | ||
- | B00000001, // Output Pin 18 | ||
- | B01000000, // Output Pin 19 | ||
- | B00000010, // Output Pin 20 | ||
- | B00100000, // Output Pin 21 | ||
- | B00000100, // Output Pin 22 | ||
- | B00010000, // Output Pin 23 | ||
- | B00001000, // Output Pin 24 | ||
- | }; | ||
- | |||
- | int animation[2]; | ||
- | const int ANIMATION_COUNT = sizeof(animation) / sizeof(int); | ||
- | |||
- | unsigned long nextAnimationUpdate[2]; | ||
- | |||
- | void led_setup() { | ||
- | pinMode(LED_DATA_PIN, | ||
- | pinMode(LED_SHIFT_CLOCK_PIN, | ||
- | pinMode(LED_STORAGE_CLOCK_PIN, | ||
- | for (int i = 0; i < ANIMATION_COUNT; | ||
- | animation[i] = -1; | ||
- | nextAnimationUpdate[i] = 0; | ||
- | } | ||
- | } | ||
- | |||
- | void led_update() { | ||
- | digitalWrite(LED_STORAGE_CLOCK_PIN, | ||
- | int data = 0; | ||
- | for (int i = 0; i < ANIMATION_COUNT; | ||
- | if (animation[i] >= 0) { | ||
- | data = data | LED_MAP[animation[i] + 4*i]; | ||
- | } | ||
- | } | ||
- | |||
- | shiftOut(LED_DATA_PIN, | ||
- | digitalWrite(LED_STORAGE_CLOCK_PIN, | ||
- | } | ||
- | |||
- | void led_loop() { | ||
- | for (int i = 0; i < ANIMATION_COUNT; | ||
- | if (nextAnimationUpdate[i] <= millis() && animation[i] >= 0) { | ||
- | animation[i] = animation[i] + 1; | ||
- | if (animation[i] > 3) { | ||
- | animation[i] = -1; | ||
- | } | ||
- | |||
- | led_update(); | ||
- | nextAnimationUpdate[i] = millis() + 500; | ||
- | } | ||
- | } | ||
- | } | ||
- | |||
- | void startAnimation(String name) { | ||
- | if (name.equals(" | ||
- | animation[0] = 0; | ||
- | } | ||
- | else if (name.equals(" | ||
- | animation[1] = 0; | ||
- | } | ||
- | |||
- | nextAnimationUpdate[1] = millis() + 500; | ||
- | led_update(); | ||
- | } | ||
- | |||
- | // -------------------------------------------------------------------------------------------------- | ||
- | // Program | ||
- | // -------------------------------------------------------------------------------------------------- | ||
- | |||
- | #define MAX_COMMAND_SIZE 50 | ||
- | #define MAX_FILENAME_SIZE 12 | ||
- | |||
- | TMRpcm _audio; | ||
- | |||
- | class PinballProgram { | ||
- | char* _command; | ||
- | char* _fileName; | ||
- | byte _inputCount; | ||
- | unsigned long* _inputLocks; | ||
- | const byte* _inputPins; | ||
- | byte* _inputPinStates; | ||
- | |||
- | void executeProgram(int i) { | ||
- | if (_audio.isPlaying()) { | ||
- | _audio.stopPlayback(); | ||
- | } | ||
- | |||
- | sprintf(_fileName, | ||
- | File file = SD.open(_fileName, | ||
- | if (!file) { | ||
- | display-> | ||
- | return; | ||
- | } | ||
- | int pos = 0; | ||
- | while (file.available()) { | ||
- | char ch = file.read(); | ||
- | if (ch == ' | ||
- | _command[pos] = ' | ||
- | executeCommand(); | ||
- | pos = 0; | ||
- | } | ||
- | else if (pos < MAX_COMMAND_SIZE) { | ||
- | if (ch != ' | ||
- | _command[pos] = ch; | ||
- | ++pos; | ||
- | } | ||
- | } | ||
- | } | ||
- | |||
- | _command[pos] = ' | ||
- | executeCommand(); | ||
- | file.close(); | ||
- | } | ||
- | |||
- | void executeCommand() { | ||
- | if (!strncmp(_command, | ||
- | strnmove(_fileName, | ||
- | _audio.play(_fileName); | ||
- | } | ||
- | else if (!strncmp(_command, | ||
- | display-> | ||
- | } | ||
- | else if (!strncmp(_command, | ||
- | display-> | ||
- | } | ||
- | else if (!strncmp(_command, | ||
- | display-> | ||
- | } | ||
- | } | ||
- | |||
- | public: | ||
- | PinballProgram(int inputCount, const byte* inputPins) : | ||
- | _command(new char[MAX_COMMAND_SIZE + 1]), | ||
- | _fileName(new char[MAX_FILENAME_SIZE + 1]), | ||
- | _inputCount(inputCount), | ||
- | _inputLocks(new unsigned long[inputCount]), | ||
- | _inputPins(inputPins), | ||
- | _inputPinStates(new byte[inputCount]) | ||
- | { | ||
- | _audio.speakerPin = SPEAKER_PIN; | ||
- | for (int i = 0; i < _inputCount; | ||
- | _inputLocks[i] = 0; | ||
- | _inputPinStates[i] = 0; | ||
- | pinMode(_inputPins[i], | ||
- | } | ||
- | |||
- | if (!SD.begin(SD_CARD_CHIP_SELECT_PIN)) { | ||
- | display-> | ||
- | return; | ||
- | } | ||
- | } | ||
- | |||
- | void init() { | ||
- | executeProgram(0); | ||
- | } | ||
- | |||
- | void loop() { | ||
- | unsigned long now = millis(); | ||
- | for (int i = 0; i < _inputCount; | ||
- | if (_inputLocks[i] < now) { | ||
- | int state = digitalRead(_inputPins[i]); | ||
- | if (state == HIGH) { | ||
- | _inputPinStates[i] = 0; | ||
- | } | ||
- | else { | ||
- | if (_inputPinStates[i] < 100) { | ||
- | ++_inputPinStates[i]; | ||
- | } | ||
- | else { | ||
- | executeProgram(i + 1); | ||
- | } | ||
- | } | ||
- | } | ||
- | } | ||
- | } | ||
- | }; | ||
- | |||
- | PinballProgram* program; | ||
- | |||
- | // -------------------------------------------------------------------------------------------------- | ||
- | // Main | ||
- | // -------------------------------------------------------------------------------------------------- | ||
- | |||
- | void setup() { | ||
- | display = new PinballDisplay(); | ||
- | program = new PinballProgram(INPUT_COUNT, | ||
- | led_setup(); | ||
- | program-> | ||
- | } | ||
- | |||
- | void loop() { | ||
- | display-> | ||
- | program-> | ||
- | led_loop(); | ||
- | } | ||
- | </ |
arduino/pinball.1416422968.txt.gz · Zuletzt geändert: 2020/10/13 14:25 (Externe Bearbeitung)