/* A / B Fake - Geber per Software mit Hilfe von Tone-Funktion
ACHTUNG -- die ganzen Berechnung erfolgen in Micro Sekunden / micros
*/
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // Initialisierung abgeschrieben !
const byte speedm_Pb = 2; // Taster Fake-Geber langsamer
const byte speedp_Pb = 3; // Taster Fake-Geber schneller
const byte dir_Sw = 4; // Schalter zur Richtungsvorgabe
const byte Reset_Pb = 5; // Taster Reset Fake-Geber
const byte Tone_Out = 8; // Ausgang Ton-Signal
const byte Enc_B_Out = 9; // Encoder Spur-A Ausgang low => on
const byte Enc_B_Out = 10; // Encoder Spur-B Ausgang npn-System
unsigned int frequenz = 0; // theoretische Frequenz vom eingelesenen Fake-Geber
volatile unsigned long highTime = 0; // Impulsdauer Zähler
volatile unsigned long lowTime = 0; // Pausendauer Zähler
volatile unsigned long startmicros = 0; // Die Zeiten sind 2-mal so lang wie die Zählertaktzeit !!!
volatile byte bin_fake_counter = 0; // Binärer Zähler 0-3 als Grundlage
volatile boolean bin_fake_0 = 0; // Bit-0 in bin_fake_counter
volatile boolean bin_fake_1 = 0; // Bit-1 in bin_fake_counter
volatile byte gray_fake_counter = 0; // Gray-Code Zähler 0-3 zur Impulsausgabe
volatile boolean gray_fake_0 = 0; // Bit-0 in gray_fake_counter
volatile boolean gray_fake_1 = 0; // Bit-1 in gray_fake_counter
volatile unsigned long actualtime = 0; // Zähler ab Programmstart in ca. Microsekunden !!!
volatile unsigned long difftime = 0; // Differenzzeit / 1/4-Taktzeit für Fake-Encoder in mys.
void setup() {
lcd.init();
lcd.backlight();
// Serial.begin(115200);
pinMode(speedm_Pb, INPUT_PULLUP);
pinMode(speedp_Pb, INPUT_PULLUP);
pinMode(dir_Sw, INPUT_PULLUP);
pinMode(Reset_Pb, INPUT_PULLUP);
pinMode(Tone_Out, OUTPUT);
pinMode(Enc_A_Out, OUTPUT);
pinMode(Enc_B_Out, OUTPUT);
attachInterrupt(0, messung, CHANGE); // automatischer Aufruf der Funktion "messung",
// wenn Pin-2 mit Ausgang verbunden wird
// NICHT in Loop aufrufen !!!
actualtime = 0; // aktuelle Zeit auf 0
difftime = 0; // Timerzeit in mys !!!
}
//---------------------------------------------------------------------------------------------------------------------------------
// !!! BIS HIER HIN ALLES NEU !!!
// Fake-Encoder mit 4-facher "Tone-Frequenz" endlos laufen lassen
void gray_fake_encoder () {
if (millis() >= actualtime + difftime) { // oder so: // if (millis() - difftime >= actualtime)
actualtime = millis(); // aktuelle Zeit neu setzen ...
if ((PIND >> 3) & 1) { // DrehrichtungsVORGABE erkennung / 1 => Zähler +, 0 => Zähler -
if (bin_fake_counter == 3) { // wenn der Zähler = 3 dann OHNE Hochzählen sofort auf 0
bin_fake_counter = 0;
} else {
bin_fake_counter++; // Counterclockwise, definiert rechts rum von 0 bis 3
}
} else {
if (bin_fake_counter == 0) { // wenn der Zähler = 0 dann OHNE Runterzählen sofort auf 3
bin_fake_counter = 3;
} else {
bin_fake_counter--;
}
}
// Bin to Gray -- "bin_fake_counter" in "gray_fake_counter" umwandeln
gray_fake_1 = bitRead(bin_fake_counter, 1); // gray Bit-1 = bin Bit-1, 1 zu 1 kopieren
gray_fake_0 = ( bitRead(bin_fake_counter, 1) ^ bitRead(bin_fake_counter, 0) ); // gray Bit-0 = bin Bit-1 EXOR bin Bit-0 !!!
bitWrite(gray_fake_counter, 0, gray_fake_0); // gray_fake_counter mit Bit-0 und Bit-1 laden
bitWrite(gray_fake_counter, 1, gray_fake_1);
// Bits nacheinander auf Ausgänge ausgeben - recht lagsam
// digitalWrite(Enc_A_Out, ! gray_fake_0); // Encoder Spur-A und B über LED anzeigen
// digitalWrite(Enc_B_Out, ! gray_fake_1); // LED leuchtet bei Encoder = 0 !!!
// jetzt direkt in Ausgangsport schreiben / ACHTUNG vorher abfragen ob 1 oder 0 gesetzt werden soll
if ( gray_fake_0 == 0 ) { // PortB1 / PIN-D8 schreiben
PORTB &= B11111110;
} else {
PORTB |= B00000001;
}
if ( gray_fake_1 == 0 ) { // PortB1 / PIN-D9 schreiben
PORTB &= B11111101;
} else {
PORTB |= B00000010;
} // fertig
// Werte zum Test auf`s Display schreiben
/*
lcd.setCursor(0, 0);
lcd.print(bin_fake_counter);
lcd.setCursor(3, 0);
lcd.print(gray_fake_counter);
lcd.setCursor(0, 1);
lcd.print( highTime); // Die Zeit ist gleich 2-mal der "difftime"
lcd.setCursor(8, 1);
lcd.print( lowTime); // Die Zeit ist gleich 2-mal der "difftime"
*/
}
}
//---------------------------------------------------------------------------------------------------------------------------------
void loop() {
gray_fake_encoder ();
frequenz = 1000 / ( highTime + lowTime ); // theoretische Fake-Geber Frequenz in Hz
/* lcd.setCursor(0, 0);
lcd.print( difftime*2);
lcd.setCursor(7, 0);
lcd.print( highTime);
lcd.setCursor(12,0);
lcd.print( lowTime);
*/ lcd.setCursor(0, 1);
lcd.print(frequenz);
// lcd.setCursor(6,1);
// lcd.print("Hz FG");
if (digitalRead(Reset_Pb) == LOW) { // Reset-Taster für LCD-Display ...
lcd.clear();
}
if (digitalRead(speedm_Pb) == LOW) { // Speed-minus-Taster für difftime / Taktzeit Fake-Geber
if ( difftime > 0 ) {
difftime--;
lcd.clear();
}
}
if (digitalRead(speedp_Pb) == LOW) { // Speed-plus-Taster für difftime / Taktzeit Fake-Geber
difftime++;
lcd.clear();
}
}
//---------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------
// Funktion an Interrupt-0 / an Pin-2, Messung der Impuls- und Pausendauer durch Flankenauswertung
void messung() {
if ((PIND >> 2) & 1) {
// lowTime = micros() - startmicros;
lowTime = millis() - startmicros;
// ilowTime = ilowTime + lowTime;
} else {
// highTime = micros() - startmicros;
highTime = millis() - startmicros;
// ihighTime = ihighTime + highTime;
}
// startmicros = micros();
startmicros = millis();
}
//---------------------------------------------------------------------------------------------------------------------------------
// ENDE des Ganzen ...