// ============================================================ // CONRAD WEICHEN-PRUEFGERAET // ARDUINO NANO // // PWM-WECHSELSPANNUNG UEBER DIE VORHANDENE BRUECKE // // Pin 3 = PWM // Pin 2 = Richtung / Polaritaet // // Die vorhandene Hardware erzeugt daraus: // // PWM + LOW // PWM + HIGH // // und damit eine Wechselspannung am Ausgang. // // ------------------------------------------------------------ // // A6 = Frequenz-Grundeinstellung // 50 ... 200 Hz // // A7 = Tastverhaeltnis // 25 ... 100 % // // A0 = EIN // A1 = AUS // // A2 = Frequenz PLUS // A3 = Frequenz MINUS // // + / - veraendert die Frequenz in 5-Hz-Schritten. // // ------------------------------------------------------------ // // Frequenzbereich: // // 50 Hz ... 200 Hz // // Schrittweite: // // 5 Hz // // ------------------------------------------------------------ // // WICHTIG: // // Die Frequenz ist die komplette Wechselperiode. // Die Polaritaet wird bei jeder halben Periode gewechselt. // // Beispiel: // // 50 Hz -> 10 ms pro kompletter Periode // 5 ms je Polaritaet // // 100 Hz -> 10 ms pro kompletter Periode // 5 ms je Polaritaet // // 200 Hz -> 5 ms pro kompletter Periode // 2,5 ms je Polaritaet // // ============================================================ // ============================================================ // PINBELEGUNG // ============================================================ const byte PWM_PIN = 3; const byte RICHTUNG_PIN = 2; const byte POTI_FREQ = A6; const byte POTI_PWM = A7; const byte TASTER_EIN = A0; const byte TASTER_AUS = A1; const byte TASTER_PLUS = A2; const byte TASTER_MINUS = A3; // ============================================================ // EINSTELLUNGEN // ============================================================ const int FREQUENZ_MIN = 50; const int FREQUENZ_MAX = 200; const int FREQUENZ_SCHRITT = 5; const int PWM_MIN = 25; const int PWM_MAX = 100; // ============================================================ // ZUSTAND // ============================================================ volatile bool ausgabeEin = false; volatile bool polaritaet = false; // ============================================================ // WERTE // ============================================================ volatile int frequenz = 50; volatile int tastverhaeltnis = 25; // ============================================================ // TIMER 1 // // 16 MHz Arduino Nano // // Timer1 mit Prescaler 8: // // 16 MHz / 8 = 2 MHz // // 1 Timer-Schritt = 0,5 us // // ============================================================ // ============================================================ // TIMER INITIALISIEREN // ============================================================ void timerInitialisieren() { noInterrupts(); TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; // CTC-Modus TCCR1B |= (1 << WGM12); // Prescaler 8 TCCR1B |= (1 << CS11); // Compare Interrupt TIMSK1 |= (1 << OCIE1A); interrupts(); } // ============================================================ // TIMER INTERRUPT // // Hier wird die Polaritaet umgeschaltet. // // Pin 2: // LOW = eine Polaritaet // HIGH = andere Polaritaet // // Pin 3 liefert PWM. // // ============================================================ ISR(TIMER1_COMPA_vect) { if (!ausgabeEin) { // Alles AUS PORTD &= ~(1 << PD3); PORTD &= ~(1 << PD2); polaritaet = false; return; } // ---------------------------------------------------------- // POLARITAET WECHSELN // ---------------------------------------------------------- polaritaet = !polaritaet; if (polaritaet) { PORTD |= (1 << PD2); } else { PORTD &= ~(1 << PD2); } } // ============================================================ // FREQUENZ EINSTELLEN // ============================================================ void timerFrequenzAktualisieren() { noInterrupts(); // Eine komplette Periode besteht aus // zwei Polaritaeten. // // Deshalb brauchen wir einen Interrupt // bei der halben Periodendauer. unsigned long halbperiode = 1000000UL / (2UL * frequenz); // Timer laeuft mit 2 MHz. // // 1 Tick = 0,5 us unsigned long ticks = halbperiode * 2UL; if (ticks < 1) { ticks = 1; } if (ticks > 65535) { ticks = 65535; } OCR1A = (uint16_t)(ticks - 1); interrupts(); } // ============================================================ // PWM AUSGABE // // Pin 3 wird ueber die Hardware-PWM des Nano betrieben. // // Die PWM-Frequenz wird hier fuer die Amplitudenregelung // verwendet. // // Die eigentliche Wechselspannung entsteht durch das // Umschalten der Polaritaet ueber Pin 2. // // ============================================================ void pwmAusgabeAktualisieren() { int wert; noInterrupts(); wert = tastverhaeltnis; interrupts(); // 25...100 % // // 25 % -> PWM 64 // 100 % -> PWM 255 int pwmWert = map(wert, 25, 100, 64, 255); pwmWert = constrain(pwmWert, 0, 255); analogWrite(PWM_PIN, pwmWert); } // ============================================================ // AUSGABE STARTEN // ============================================================ void ausgabeStarten() { noInterrupts(); // Ausgang zuerst komplett ausschalten analogWrite(PWM_PIN, 0); PORTD &= ~(1 << PD2); polaritaet = false; // Ausgabe aktivieren ausgabeEin = true; interrupts(); // Frequenz einstellen timerFrequenzAktualisieren(); // PWM einstellen pwmAusgabeAktualisieren(); Serial.println("Ausgabe EIN"); statusAusgeben(); } // ============================================================ // AUSGABE STOPPEN // ============================================================ void ausgabeStoppen() { noInterrupts(); ausgabeEin = false; // Beide Ausgaenge AUS PORTD &= ~(1 << PD3); PORTD &= ~(1 << PD2); polaritaet = false; interrupts(); analogWrite(PWM_PIN, 0); Serial.println("Ausgabe AUS"); statusAusgeben(); } // ============================================================ // POTI FREQUENZ // ============================================================ void frequenzPoti() { static unsigned long letzteMessung = 0; if (millis() - letzteMessung < 100) { return; } letzteMessung = millis(); int wert = analogRead(POTI_FREQ); int neueFrequenz = map(wert, 0, 1023, FREQUENZ_MIN, FREQUENZ_MAX); neueFrequenz = constrain(neueFrequenz, FREQUENZ_MIN, FREQUENZ_MAX); if (neueFrequenz != frequenz) { frequenz = neueFrequenz; timerFrequenzAktualisieren(); statusAusgeben(); } } // ============================================================ // POTI TASTVERHAELTNIS // ============================================================ void pwmPoti() { static unsigned long letzteMessung = 0; if (millis() - letzteMessung < 100) { return; } letzteMessung = millis(); int wert = analogRead(POTI_PWM); int neuerWert = map(wert, 0, 1023, PWM_MIN, PWM_MAX); neuerWert = constrain(neuerWert, PWM_MIN, PWM_MAX); if (neuerWert != tastverhaeltnis) { tastverhaeltnis = neuerWert; pwmAusgabeAktualisieren(); statusAusgeben(); } } // ============================================================ // PLUS TASTER // // Frequenz +5 Hz // ============================================================ void plusTaster() { static bool alt = HIGH; static unsigned long letzteZeit = 0; bool neu = digitalRead(TASTER_PLUS); if (alt == HIGH && neu == LOW) { if (millis() - letzteZeit >= 50) { letzteZeit = millis(); frequenz += FREQUENZ_SCHRITT; if (frequenz > FREQUENZ_MAX) { frequenz = FREQUENZ_MAX; } timerFrequenzAktualisieren(); statusAusgeben(); } } alt = neu; } // ============================================================ // MINUS TASTER // // Frequenz -5 Hz // ============================================================ void minusTaster() { static bool alt = HIGH; static unsigned long letzteZeit = 0; bool neu = digitalRead(TASTER_MINUS); if (alt == HIGH && neu == LOW) { if (millis() - letzteZeit >= 50) { letzteZeit = millis(); frequenz -= FREQUENZ_SCHRITT; if (frequenz < FREQUENZ_MIN) { frequenz = FREQUENZ_MIN; } timerFrequenzAktualisieren(); statusAusgeben(); } } alt = neu; } // ============================================================ // EIN TASTER // ============================================================ void einTaster() { static bool alt = HIGH; static unsigned long letzteZeit = 0; bool neu = digitalRead(TASTER_EIN); if (alt == HIGH && neu == LOW) { if (millis() - letzteZeit >= 50) { letzteZeit = millis(); ausgabeStarten(); } } alt = neu; } // ============================================================ // AUS TASTER // ============================================================ void ausTaster() { static bool alt = HIGH; static unsigned long letzteZeit = 0; bool neu = digitalRead(TASTER_AUS); if (alt == HIGH && neu == LOW) { if (millis() - letzteZeit >= 50) { letzteZeit = millis(); ausgabeStoppen(); } } alt = neu; } // ============================================================ // STATUS // ============================================================ void statusAusgeben() { noInterrupts(); int f = frequenz; int t = tastverhaeltnis; bool e = ausgabeEin; interrupts(); Serial.print("Ausgabe: "); if (e) { Serial.print("EIN"); } else { Serial.print("AUS"); } Serial.print(" Frequenz: "); Serial.print(f); Serial.print(" Hz"); Serial.print(" Tastverhaeltnis: "); Serial.print(t); Serial.println(" %"); } // ============================================================ // SETUP // ============================================================ void setup() { // ---------------------------------------------------------- // AUSGAENGE // ---------------------------------------------------------- pinMode(PWM_PIN, OUTPUT); pinMode(RICHTUNG_PIN, OUTPUT); // Alles sicher AUS analogWrite(PWM_PIN, 0); digitalWrite(RICHTUNG_PIN, LOW); // ---------------------------------------------------------- // TASTER // ---------------------------------------------------------- pinMode(TASTER_EIN, INPUT_PULLUP); pinMode(TASTER_AUS, INPUT_PULLUP); pinMode(TASTER_PLUS, INPUT_PULLUP); pinMode(TASTER_MINUS, INPUT_PULLUP); // ---------------------------------------------------------- // SERIELL // ---------------------------------------------------------- Serial.begin(115200); Serial.println(); Serial.println("================================="); Serial.println(" CONRAD WEICHEN-PRUEFGERAET"); Serial.println("================================="); Serial.println("PWM : Pin 3"); Serial.println("Polaritaet: Pin 2"); Serial.println("Frequenz : A6 / +/-"); Serial.println("PWM : A7"); Serial.println("EIN : A0"); Serial.println("AUS : A1"); Serial.println(); // ---------------------------------------------------------- // POTI STARTWERTE // ---------------------------------------------------------- frequenz = map(analogRead(POTI_FREQ), 0, 1023, FREQUENZ_MIN, FREQUENZ_MAX); tastverhaeltnis = map(analogRead(POTI_PWM), 0, 1023, PWM_MIN, PWM_MAX); frequenz = constrain(frequenz, FREQUENZ_MIN, FREQUENZ_MAX); tastverhaeltnis = constrain(tastverhaeltnis, PWM_MIN, PWM_MAX); // ---------------------------------------------------------- // TIMER // ---------------------------------------------------------- timerInitialisieren(); timerFrequenzAktualisieren(); // ---------------------------------------------------------- // AUS // ---------------------------------------------------------- ausgabeStoppen(); statusAusgeben(); } // ============================================================ // LOOP // ============================================================ void loop() { // Frequenz-Poti frequenzPoti(); // Tastverhaeltnis-Poti pwmPoti(); // EIN / AUS einTaster(); ausTaster(); // Frequenz + / - plusTaster(); minusTaster(); } /* Beispiel bei 100 Hz: Pin 2: LOW ───── HIGH ───── LOW ───── HIGH ... <--- 5 ms ---> Ausgang: + - + - ┌───┐ ┌───┐ ┌───┐ │ │ │ │ │ │ ────────┘ └───┘ └───┘ └──── + und − verändern dabei die Frequenz 50, 55, 60 ... 195, 200 Hz. A6 kann die Frequenz zusätzlich als Grund-/Direkteinstellung vorgeben und A7 stellt das Tastverhältnis 25–100 % */