CharlieDemo.ino

/** * CharlieDemo * Zeigt das Prinzip von CharliePlexing für ein Viessmann Ks-Signal 4045. * * $Id: CharlieDemo.ino 15125 2022-04-10 08:05:56Z martin $ * * (C) 2022 by Martin Pischky (martin@pischky.de) * * Beschreibung: * Es werden die Pins D8..D12 abgefragt. Ist einer davon mit Masse verbunden * wird das entsprechende Signalbild angezeigt. Dabei wird Charlieplexing * (in Modellbahnerkreisen auch als IngoPlexing bekannt) verwendet. Die * vier Pins D14..D17 werden dabei mit etwa 100Hz angesteuert. Hier kann * direkt ein Ks-Signal von Viessmann (4045) angeschlossen werden. Die * Vorwiderstände sollten etwa 180 Ohm betragen. * * Dieses ist nur ein Programm was die Funktion von CharliePlexing * demonstrieren soll. Dinge wie Blinken und Überblenden sind nicht * implementiert. Ebenso sollten natürlich Hardware-Timer verwendet werden. * * Benutzt wurden: * Arduino Nano clone mit CH340 oder Arduino Nano Every * Arduino IDE 1.8.19 (https://www.arduino.cc) * ArduinoSTL 1.3.3 (https://github.com/mike-matera/ArduinoSTL) * Sloeber V4.4.0 (https://eclipse.baeyens.it/) * * Hinweis: * Select "Arduino AVR Boards" by Arduino 1.8.2 in Boardmanager/Platform and Boards * (see https://github.com/mike-matera/ArduinoSTL/issues/56) * For Arduino Nano Every use: with Registers emulation "ATMEGA328" * */ #if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) #include <Arduino.h> #include <ArduinoSTL.h> // use ArduinoSTL 1.3.3 https://github.com/mike-matera/ArduinoSTL #endif #include <cstdint> // uint8_t #include <iostream> // cout, endl #include "KsSignalCharliePlexer.hpp" // class KsSignalCharliePlexer using std::uint8_t; using std::cout; using std::endl; using std::ostream; constexpr uint8_t TRIGGER = 2; // Ausgang für Oszilloskop Trigger constexpr uint8_t BASE_SIGNAL_PIN = 14; // Arduino Pins D14..D17 für das Signal // (Atmega328P: PC0..PC3) constexpr uint8_t BASE_INPUT_PIN = 8; // Arduino Pins D8..D12 als Eingang // (Atmega328P: PB0..PB4) /** * Instanz des CharliePlexers. */ KsSignalCharliePlexer kscp{ BASE_SIGNAL_PIN }; /** * Lese Eingänge und ermittle das Signalbild wenn ein Pin LOW ist. * Wenn kein Pin mit LOW gefunden wurde ist der Rückgabewert 0. * Wir verwenden "uint16_t" statt "SignalBild" als Rückgabetyp damit Sloeber * glücklich ist. */ KsSignalCharliePlexer::SignalBild readSignalBild() { for (int i = 0; i < 5; ++i) { if (digitalRead(BASE_INPUT_PIN + i) == LOW) { switch (i) { case 0: return HALT; case 1: return FAHRT; case 2: return FAHRT_ZS3; case 3: return HALT_ERWARTEN; case 4: return FAHRT_ZS3_ZS3V; } } } return 0; } /** * Schöne Ausgabe des Signalbildes. */ const char* signalBildString(KsSignalCharliePlexer::SignalBild sb) { if (sb == HALT) return "HALT"; if (sb == FAHRT) return "FAHRT"; if (sb == FAHRT_ZS3) return "FAHRT_ZS3"; if (sb == HALT_ERWARTEN) return "HALT_ERWARTEN"; if (sb == FAHRT_ZS3_ZS3V) return "FAHRT_ZS3_ZS3V"; return "unbekannt"; } /** * Lasse die eingebaute LED auf dem Arduino Board blinken. */ void alive() { static uint8_t count = 0; if (count == 0) digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); count = (count + 1) % 100; } void setup() { // Starte den seriellen Port mit 115200 bps und warte. Serial.begin(115200); while (!Serial) { ; // Warte auf den seriellen Port. Für native USB Ports erforderlich. } pinMode(LED_BUILTIN, OUTPUT); pinMode(TRIGGER, OUTPUT); for(int i = 0; i < 5; ++i) pinMode(BASE_INPUT_PIN + i, INPUT_PULLUP); cout << "setup(): kscp.status=0b" << kscp.getStatus() << " " << signalBildString(kscp.getStatus()) << endl; kscp.setAllTristate(); cout << "setup(): kscp.setStatus(HALT)" << endl; kscp.setStatus(HALT); cout << "setup(): kscp.status=0b" << kscp.getStatus() << " " << signalBildString(kscp.getStatus()) << endl; } void loop() { alive(); if (KsSignalCharliePlexer::SignalBild nb = readSignalBild(); nb != 0 && nb != kscp.getStatus()) { cout << "loop() : kscp.setStatus(0b" << nb << ")" << " " << signalBildString(nb) << endl; kscp.setStatus( nb ); } digitalWrite(TRIGGER, !digitalRead(TRIGGER)); // Trigger Ausgang toggeln kscp.cycle(); }