// Generate three phase square wave using lookup table
//
// A pushbutton can reverse the phases and this
// reversal is detected by monitoring code.
// Code added to detect reversal within 2/3 cycle using array search
// with memmem() function
// Phase tables have an extra position added which duplicates the first
// array value. This allows memmem() to complete a search of the table
// values using any two consecutive values without having to wrap around.
const byte tableFWD[] {3, 1, 5, 4, 6, 2, 3}; // output bit pattern
const byte tableREV[] {5, 1, 3, 2, 6, 4, 5}; // output bit pattern
const byte tableLOSS[] {4, 0, 2, 2, 6, 4, 4}; // output bit pattern - missing phase 'R' from tableREV
unsigned long tickInterval = 750000; // One second
const byte searchLen = sizeof(tableFWD);
const byte maxPhase = searchLen - 1; // Only six values used to generate phases
// Using analog pins since they're uncommitted
const byte phaseR = A0;
const byte phaseY = A1;
const byte phaseB = A2;
const byte pbReverser = 10; // A pushbutton
const byte pbTeach = 8; // A pushbutton
byte phRIn, phRLast, phR_OS, phRLatch;
byte phYIn, phYLast, phY_OS, phYLatch;
byte phBIn, phBLast, phB_OS, phBLatch;
byte phaseMemory, phaseError;
byte phaseOK = 1;
void setup() {
Serial.begin(115200);
Serial.println(__FILE__);
pinMode(phaseR, OUTPUT);
pinMode(phaseY, OUTPUT);
pinMode(phaseB, OUTPUT);
pinMode(pbReverser, INPUT_PULLUP);
pinMode(pbTeach, INPUT_PULLUP);
}
void loop() {
static byte portData, phaseIndex, transition;
static unsigned long currentMillis;
byte sampleArray[2];
byte sampleIndex = 0;
// Generate a three phase square wave on A0-A2
if (micros() - currentMillis >= tickInterval) { // time to update
// read port // wipe low three bits
portData = PINC & 0xf8;
if (digitalRead(pbReverser) == HIGH) {
portData |= tableFWD[phaseIndex++];
}
else {
portData |= tableREV[phaseIndex++]; // OR in the table data and increment
}
if (digitalRead(pbTeach) == LOW) {
portData |= tableLOSS[phaseIndex++]; // induce phase loss
}
PORTC = portData; // Write the new data back out to the port
currentMillis = micros(); // reset timer
//
// override a phase to induce a phase loss error, detect below
}
if (phaseIndex >= maxPhase) phaseIndex = 0; // start over at index zero
//------------------------------------
// Detect phase reversal or phase loss
// Monitor phases 'R', 'Y', AND 'B' for changes
phRIn = PINC & 0x01; // Get current input status
phYIn = PINC & 0x02; // Get current input status
phBIn = PINC & 0x04; // Get current input status
phR_OS = (phRIn ^ phRLast); // Sense a change of state on each phase
phRLast = phRIn;
phY_OS = (phYIn ^ phYLast);
phYLast = phYIn;
phB_OS = (phBIn ^ phBLast);
phBLast = phBIn;
if (phR_OS or phY_OS or phB_OS) { // one of the phases changed state
sampleArray[0] = sampleArray[1]; // two stage shift register creates a section
// of the repeating square wave pattern
sampleArray[1] = PINC & 0x07; // retain low three bits of new port data
// which represents the digitized phases
if (memmem(tableFWD, searchLen, sampleArray, 2)) { // search the phase table for a match
// with the last two phase changes
Serial.print("direction FWD\t");
Serial.println(sampleArray[1]);
}
else if (memmem(tableREV, searchLen, sampleArray, 2)) { // search the reverse table
Serial.print("direction REV\t");
Serial.println(sampleArray[1]);
}
else {
Serial.print("phase loss\t"); // if no match found in either direction table,
// there is a missing phase
Serial.println(sampleArray[1]);
}
}
} // end of loop()