Timer1 Quadrature - digitalWrite & digitalRead will not work together

Hello! Still sorting out my previous problem, but I think I was finally able to work out the signals I was generating. Right now, the digitalWrite and digitalRead are conflicting with each other. I am taking an input from a potentiometer that is supposed to adjust then update the frequency every time the value changes by using a method called resetICR(). At the same time, I had wanted to use a switch to eventually "change" the direction of the quadrature signals (which is just really updating the output compare registers). However, even with a brief testing of the switch it refuses to work alongside the interrupt routine. The problem always lies between reading from the switch pin (i.e digitalRead(switchPin)) or writing to the signals in the interrupt routines (i.e digitalWrite(signalA, HIGH)). What happens is that the potentiometer stops reading and nothing updates. If I take out either the digitalRead or digitalWrite, the potentiometer can read again. For this code in particular, I just wanted to be at least be able to read from the switch pin before moving on.

The parts I am using is a 10K ohm potentiometer, a switch rocker, and an Arduino MEGA 2560.

const int signalA = 9;                               // Set signal A for pin 9
const int signalB = 12;                              // Set signal B for pin 10
const int potPin = A1;                               // Set potentiometer for pin A0
const byte switchPin = 36;                           // Set switch for pin 36
boolean toggleA = 0;                                 // Toggle flag for signal A
boolean toggleB = 0;                                 // Toggle flag for signal B
int value = 0;                                       // Analog to digital valueue read in by potentiometer
int a = 0;                                           // Variable to check to see if potentiometer value has changed

byte switchState = 0;

void setup() {
  Serial.begin(9600);
  pinMode(signalA, OUTPUT);                          // Initialize signal pins to be outputs
  pinMode(signalB, OUTPUT);
  pinMode(potPin, INPUT);                            // Set potentiometer pin to be input
  pinMode(switchPin, INPUT_PULLUP);                  // The switch pin is an input pulled HIGH by an internal resistor

  cli();                                             // Stop all interrupts

  TCCR1A = 0;                                        // Set timer
  TCCR1B = 0;
  TCNT1 = 0;                                         // Set counter to 0. TCNT1 stores the timer 1 counter valueues

  ICR1 = 99;                                         // Set ICR1 = [16Mhz / (desired frequency * prescaler)] - 1
  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = OCR1A / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle
  TCCR1B |= (1 << CS11);                             // Set prescaler
                                                     // CS10, CS11, CS12 are the clock select bits for Timer 1
                                                     // Each bit corresponds to a prescaler
                                                     // In this case, enabling CS11 will set the prescaler to 8.
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);           // Enable Timer Compare Interrupt A & B

  TCCR1B |= (1 << WGM13) | (1 << WGM12);             // CTC mode with ICR1 = Clear timer when the counter reaches the compare match register
                                                     // This will set the two bits of WGM to 14
                                                     // Note: 1 << WGM12 is the same as TCCR1B = 32

  sei();                                             // Allow interrupts
}


void loop() {
  readPin();
}

void readPin() {

  int d = analogRead(potPin);                        // Analog read from potPin and assigned to value
  value = d >> 4;                                    // Shift value by 4 bits to reduce range (1023/16) for smoother transition
  switchState = digitalRead(switchPin);              // read the state of the input pin (HIGH or LOW)
  if (a != value) {                                  // Check to see if potentiometer valueue has changed before updating frequency
    Serial.println(value);                           // Print value on serial monitor for debugging
    a = value;                                       // Change a to value to show that potentiometer valueue has changed
    if (value <= 48 && value > 0) {                  // Set a limit for when potentiometer ADC valueue to 48 (49 is for 20kHz
      resetICR(49);                                  // Set valueue for maximum frequency of 20kHz
    }
    else if (a == 0) {                               // Stop all interrupts if potentiometer value is 0
      cli();
    }
    else {
      resetICR(value);                               // Otherwise, update frequency to acceptable valueue from the potentiometer
    }
  }
}

void resetICR(int input) {
  cli();
  TCCR1A = 0;                                        // Set timers
  TCCR1B = 0;
  TCNT1 = 0;                                         // Set counter to 0. TCNT1 stores the timer 1 counter valueues

  ICR1 = input;                                      // Set ICR1 = [16Mhz / (desired frequency * prescaler)] - 1
  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = OCR1A / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle, toggling signal half a period later
  TCCR1B |= (1 << CS11);                             // Set prescaler
                                                     // CS10, CS11, CS12 are the clock select bits for Timer 1
                                                     // Each bit corresponds to a prescaler
                                                     // In this case, enabling CS11 will set the prescaler to 8.
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);           // Enable Timer Compare Interrupt A & B

  TCCR1B |= (1 << WGM13) | (1 << WGM12);             // CTC mode with ICR1 = Clear timer when the counter reaches the compare match register

  sei();                                             // Allow interrupts

}

ISR(TIMER1_COMPA_vect) {                                 // Interrupt handler. Toggle signalA
  if (toggleA) {
    digitalWrite(signalA, HIGH);
    toggleA = 0;
  }
  else {
    digitalWrite(signalA, LOW);
    toggleA = 1;
  }
}


ISR(TIMER1_COMPB_vect) {                                 // Interrupt handler. Toggle signalB
  if (toggleB) {
    digitalWrite(signalB, HIGH);
    toggleB = 0;
  }
  else {
    digitalWrite(signalB, LOW);
    toggleB = 1;
  }
}

I have several suggestions.

First, analogRead() is slow and blocking. Calling it every pass of loop() with so much going on in your program is not a good idea. You can not adjust the pot very quickly either, so loop speed response is not required.

First, I would only perform the analogRead() every 500 milliseconds. It's not clear how often you want to change the frequency, so it could be less frequently than that.

Second, I would put some sort of dead band for the size of change required around the reading so that if the pot is not moved, but the value changes by 1 or 2, you don't make any changes.

Third, I would separate the analogRead() from the adjustment of the Timer parameters. If the set point for frequency has changed enough to make a change to the timer, set a flag, adjust the timer if the flag is set, and clear the flag after adjustment.

Your right shift by 4 is what's causing confusion - the value of 'value' is hardly ever going to be above 48.

Disabling interrupts indefinitely is a no-no.

interrupts() and noInterrupts() are the portable calls for enabling and disabling interrupts (although
here the code is not very portable due to use of AVR timer.

resetICR() set the hardware counter to zero irrespective of the values of toggleA and toggleB, so
it will randomize the quadrature direction dependent on when it runs. Perhaps it should zero toggleA
and toggleB too? And you can tie in the switchState to this if you want.

Thinking about it I would have used the timer overflow interrupt and a single ISR that stepped through the 4 quadrature states, simpler and easier to code and control the phase relationship.

Thank you for the suggestions! I applied cattledog's approach and it seems to run smoother. I still had wanted to use two interrupt routines since for some reason if I had tried to use one interrupt routine for two signals, it would not output the desired frequency. I still have yet to understand why that is, but I still have difficulties using digitalRead anywhere to read in my switch to change the direction of the quadrature. That is why I had used attachtoInterrupt instead to observe the switch.

Here is the updated code. My switchPins method is my approach for switching the direction by switching the assigned signal pins.

volatile int signalA = 9;                            // Set signal A for pin 9
volatile int signalB = 12;                           // Set signal B for pin 10
const int potPin = A1;                               // Set potentiometer for pin A0
const byte switchPin = 2;                            // Set switch for pin 2

boolean toggleA = 0;                                 // Toggle flag for signal A
boolean toggleB = 0;                                 // Toggle flag for signal B
int value = 0;                                       // Analog to digital value read in by potentiometer
int a = 0;                                           // Variable to check to see if potentiometer value has changed
int intcount = 0;
volatile byte switchState = LOW;
int flag = 0;
void setup() {
  Serial.begin(9600);
  pinMode(signalA, OUTPUT);                          // Initialize signal pins to be outputs
  pinMode(signalB, OUTPUT);
  pinMode(potPin, INPUT);                            // Set potentiometer pin to be input
  pinMode(switchPin, INPUT_PULLUP);                  // The switch pin is an input pulled HIGH by an internal resistor
  attachInterrupt(digitalPinToInterrupt(switchPin), switchPins, CHANGE); // Go to interrupt routine of method switchPins every time switch is toggled

  DDRA = B11111111;

  cli();                                             // Disable all interrupts
  TCCR1A = 0;                                        // Set timer
  TCCR1B = 0;
  TCNT1 = 0;                                         // Set counter to 0. TCNT1 stores the timer 1 counter values

  ICR1 = 99;                                         // Set ICR1 = [16Mhz / (desired frequency * prescaler)] - 1
  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = OCR1A / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle
  TCCR1B |= (1 << CS11);                             // Set prescaler
  // CS10, CS11, CS12 are the clock select bits for Timer 1
  // Each bit corresponds to a prescaler
  // In this case, enabling CS11 will set the prescaler to 8.
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);           // Enable Timer Compare Interrupt A & B

  TCCR1B |= (1 << WGM13) | (1 << WGM12);             // CTC mode with ICR1 = Clear timer when the counter reaches the compare match register
  // This will set the two bits of WGM to 14
  // Note: 1 << WGM12 is the same as TCCR1B = 32
  sei();                                             // Enable all interrupts
}


void loop() {
  delay(500);
  readPin();
}

void readPin() {

  volatile int b = analogRead(potPin);               // Analog read from potPin and assigned to value

  value = b >> 4;                                    // Shift value by 4 bits to reduce range (1023/16) for smoother transition
  Serial.println((String) "value: " + value + "\t a: " + a); // Print value and a for debugging
 
  if (a >= (value-1) && (value+1) >= a){             // To prevent unstable readings from potentiometer, only update the frequency when potentiometer changes values for more than +2/-2
    flag = 0;                                        // If not, do not set flag to 1
    Serial.println("0");                             // For debugging only
  }
  else {
    flag = 1;                                        // Set flag to 1 if value from potPin is changed from +2/-2
    Serial.println("1");                             // For debugging only
  }
  a = value;                                         // Update a to equal value
  updatePin();                                       // Update the frequency only if the flag is set to 1
}

void updatePin() {
  if (flag == 1) {                                   // Check to see if flag is 1 before updating frequency
    if (value <= 51 && value > 0) {                  // Set a limit for when potentiometer ADC value to 48 (49 is for 20kHz)
      cli();                                         // Disable all interrupts
      resetICR(49);                                  // Set value
      sei();                                         // Enable all interrupts
    }
    else if (a == 0) {                               // Stop all interrupts if potentiometer value is 0
      cli();
    }
    else {
      cli();                                         // Disable all interrupts
      resetICR(value);                               // Otherwise, update frequency to acceptable value from the potentiometer
      sei();                                         // Enable all interrupts
    }
  }
  flag = 0;                                          // Once update is done, set flag to 0 again
}

void resetICR(int input) {
  TCCR1A = 0;                                        // Set timers
  TCCR1B = 0;
  TCNT1 = 0;                                         // Set counter to 0. TCNT1 stores the timer 1 counter values
  ICR1 = input;                                      // Set ICR1 = [16Mhz / (desired frequency * prescaler)] - 1

  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = OCR1A / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle, toggling signal half a period later
  TCCR1B |= (1 << CS11);                             // Set prescaler
  // CS10, CS11, CS12 are the clock select bits for Timer 1
  // Each bit corresponds to a prescaler
  // In this case, enabling CS11 will set the prescaler to 8.
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);           // Enable Timer Compare Interrupt A & B
  TCCR1B |= (1 << WGM13) | (1 << WGM12);             // CTC mode with ICR1 = Clear timer when the counter reaches the compare match register

}

void switchPins() {                                  // Change direction of quadrature                      
  int temp = signalB;
  signalB = signalA;
  signalA = temp;
  Serial.println("CHANGE");
}


ISR(TIMER1_COMPA_vect) {                                 // Interrupt handler. Toggle signalA
  if (toggleA) {
    digitalWrite(signalA, HIGH);
    PORTA = B11111111;
    toggleA = 0;
  }
  else {
    digitalWrite(signalA, LOW);
    PORTA = B00000000;
    toggleA = 1;
  }
}


ISR(TIMER1_COMPB_vect) {                                 // Interrupt handler. Toggle signalB
  if (toggleB) {
    digitalWrite(signalB, HIGH);
    toggleB = 0;
  }
  else {
    digitalWrite(signalB, LOW);
    toggleB = 1;
  }
}

MarkT:
Your right shift by 4 is what's causing confusion - the value of 'value' is hardly ever going to be above 48.

Disabling interrupts indefinitely is a no-no.

interrupts() and noInterrupts() are the portable calls for enabling and disabling interrupts (although
here the code is not very portable due to use of AVR timer.

resetICR() set the hardware counter to zero irrespective of the values of toggleA and toggleB, so
it will randomize the quadrature direction dependent on when it runs. Perhaps it should zero toggleA
and toggleB too? And you can tie in the switchState to this if you want.

Thinking about it I would have used the timer overflow interrupt and a single ISR that stepped through the 4 quadrature states, simpler and easier to code and control the phase relationship.

So I finally understood what you meant by the direction arbitrarily changing-- does this mean I have to include toggleA and toggle to be zero in my resetICR?

  intcount = 0;
  TCCR1A = 0;                                        // Set timers
  TCCR1B = 0;
  TCNT1 = 0;                                         // Set counter to 0. TCNT1 stores the timer 1 counter values
  ICR1 = input;                                      // Set ICR1 = [16Mhz / (desired frequency * prescaler)] - 1
  
  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = OCR1A / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle, toggling signal half a period later
  TCCR1B |= (1 << CS11);                             // Set prescaler
  // CS10, CS11, CS12 are the clock select bits for Timer 1
  // Each bit corresponds to a prescaler
  // In this case, enabling CS11 will set the prescaler to 8.
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);           // Enable Timer Compare Interrupt A & B
  TCCR1B |= (1 << WGM13) | (1 << WGM12);             // CTC mode with ICR1 = Clear timer when the counter reaches the compare match register
  sei();      
  toggleA = 0;
  toggleB = 0;  // Disable all interrupts

So I finally understood what you meant by the direction arbitrarily changing-- does this mean I have to include toggleA and toggleB to be zero in my resetICR?

This takes us back to the original discussion of your technique where you are modifying code which originally used timer hardware output to use compare match interrupts instead.Timer1 Quadrature Signal Generator - Signals are not the same frequency - Motors, Mechanics, Power and CNC - Arduino Forum

The original emulator code switched directions very simply with code like this

if (Command == 'F')
  {
    OCR1A = ICR1 - 1; //two different pulse widths almost 100% duty cycle
    OCR1B = OCR1A / 2; //offset by half period
    TCCR1B |= _BV(CS11);//start timer
  }

  if (Command == 'R')
  {
    OCR1B = ICR1 - 1; //two different pulse widths almost 100% duty cycle
    OCR1A = OCR1B / 2; //offset by half period
    TCCR1B |=  _BV(CS11);//start timer
  }

Using the toggle and the compare match interrupts is causing directional issues when you change frequencies.
https://forum.arduino.cc/index.php?topic=717793.0

I am kind of confused -- I was using signal A (pin 9) and signal B (pin 12) to make the PWM signals. How will I observe the signals through those outputs if they aren't connected to a pin?

void loop() {
  switchState = PIND & 0b10000000;                   // Set switchState to only observe digital pin 38
  if (changeState != switchState) {                  // If changeState does not equal the current state of the switchPin
    switchPins();                                    // Call method to change the signal pins
    changeState = switchState;                       // Set changeState to equal the current state of the switchPin
    }
  delay(100);
  readPin();                                         // Read potentiometer pin
}

void readPin() {
  volatile int temp = analogRead(potPin);            // Analog read from potPin and assigned to value
  temp = temp >> 4;                                  // Shift value by 4 bits to reduce range (1023/16) for smoother transition
  if (bufcount < 4) {                                // If the bufcount is less than 4, have it equal the value of the potPin
    buf[bufcount] = temp;
    cumulative += buf[bufcount];                     // Add and store buf into cumulative
    bufcount++;                                      // Increment bufcount
  }
  else {                                             // If bufcount is now greater than the buf size
    value = cumulative >> 2;                         // value is equal to cumulative/4
    bufcount = 0;                                    // Reset both bufcount and cumulative
    cumulative = 0;
  }
  if (potval != value) {                             // If potval does not equal value, update the frequency
    updatePin();
    potval = value;                                  // Set potval to equal value
  }
}

void updatePin() {
  if (value <= 49 && value >= 0) {                   // Set a limit for when potentiometer ADC value to 48 (49 is for 20kHz)
    cli();                                           // Disable all interrupts
    resetICR(49);                                    // Otherwise, update frequency to acceptable value from the potentiometer
    sei();                                           // Enable all interrupts
  }

  else if (value == 63) {                            // Stop all interrupts if potentiometer value is 63
    cli();                                           // 63 is the "lowest" value the potentiometer can reach
  }
  
  else {
    cli(); // Disable all interrupts
    resetICR(value);                                 // Update frequency to acceptable value from the potentiometer 
    sei();                                           // Enable all interrupts
  }
}

void resetICR(int input) {
  
  intcount = 0;
  TCCR1A = 0;                                        // Set timers
  TCCR1B = 0;
  TCNT1 = 0;                                         // Set counter to 0. TCNT1 stores the timer 1 counter values
  ICR1 = input;       
  // Set ICR1 = [16Mhz / (desired frequency * prescaler)] - 1
  
  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = OCR1A / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle, toggling signal half a period later
  TCCR1B |= (1 << CS11);                             // Set prescaler
  // CS10, CS11, CS12 are the clock select bits for Timer 1
  // Each bit corresponds to a prescaler
  // In this case, enabling CS11 will set the prescaler to 8.
  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);           // Enable Timer Compare Interrupt A & B
  TCCR1B |= (1 << WGM13) | (1 << WGM12);             // CTC mode with ICR1 = Clear timer when the counter reaches the compare match register     

  toggleA = 0;
  toggleB = 0;
}

void switchPins() {                                  // Change direction of quadrature
  int temp = signalB;                                // Create temp variable to hold pin value of signal B
  signalB = signalA;                                 // Switch signal B to equal signal A
  signalA = temp;                                    // Have signal A equal temp
  Serial.println("CHANGE");
}

ISR(TIMER1_COMPA_vect) {                             // Interrupt handler. Toggle signalA
  if (toggleA) {
    digitalWrite(signalA, HIGH);
//  if(signalA == 9){
//    PORTA = intcount;                                // This code is for the binary counter for the 12 LEDs
//    PORTC = intcount >> 4;                           // Additional port registers are shifted by 4 bits
//    intcount++;                                      // Increment counter
//  }
//  else {
//   PORTC = intcount >> 4;
//   PORTA = intcount;
//    intcount--;
//  }

//    if (signalA == 9){
//      if (intcount < 12){
//        PORTA = 1 << intcount;                           // This code is for the sweeping LEDs
//        PORTC = 1 << intcount - 4;                       // Additional port registers are shifted by 4 bits
//        intcount++;                                      // Increment counter
//      }
//      else if (intcount == 12) {                            // Clear counter once it reaches 12 since there are 12 LEDs
//        intcount = 0;
//      }
//    }
//    else {
//      if (intcount < 12){
//        PORTC = 0b10000000 >> intcount;                       // Additional port registers are shifted by 4 bits
//        PORTA = 0b100000000 >> intcount-3;                           // This code is for the sweeping LEDs
//        intcount++;                                      // Increment counter
//       }
//      else if (intcount == 12) {                            // Clear counter once it reaches 12 since there are 12 LEDs
//        intcount = 0;
//      }
//    }
    toggleA = 0;
  }
  else {
    digitalWrite(signalA, LOW);
    toggleA = 1;
  }
}


ISR(TIMER1_COMPB_vect) {                             // Interrupt handler. Toggle signalB
  if (toggleB) {
    digitalWrite(signalB, HIGH);
    toggleB = 0;
  }
  else {
    digitalWrite(signalB, LOW);
    toggleB = 1;
  }
}

How will I observe the signals through those outputs if they aren't connected to a pin?

What is preventing you from designing your program around the hardware output pins for Timer1?

I'm certain there are methods for quadrature emulation and direction reversal using arbitrary pins, but you may need to start from a different place than code which was written for timer hardware output pins.

I had previously compiled the 2015 code, but I was unable to observe the output on pins 9 and 10-- which is why I had used the compare match interrupts and altered the code. But I'm still not sure which registers contribute to the hardware outputs?

I had also soldered my design onto the board already-- but perhaps I could try to fix that. I also removed the toggle and had it change states as shown below.

ISR(TIMER1_COMPA_vect) {                             // Interrupt handler. Toggle signalA

    digitalWrite(signalA, switchPinStateA);
    switchPinStateA = ~switchPinStateA;
}

I had previously compiled the 2015 code, but I was unable to observe the output on pins 9 and 10-- which is why I had used the compare match interrupts and altered the code. But I'm still not sure which registers contribute to the hardware outputs?

The original code is pretty solid and has been used successfully by several others.
https://forum.arduino.cc/?topic=383189#msg3821429

The parts I am using is a 10K ohm potentiometer, a switch rocker, and an Arduino MEGA 2560.

The timer1 hardware output pins on the Mega are OC1A pin 11, and OC1B pin 12. I think you should be able to switch to them directly without any changes in the original code written for the UNO on pins 9 and 10. Timer1 register code should be the same for the two models. Can you switch your pin9 connection to pin 11 on your board?

I don't know what pins you have available on the Mega, but with multiple 16 bit timers available you should be able to find some thing free.

BTW the timer pin assignements for the Arduino Mega are:

port/bit   timers  register  arduino pin number
G,5          0      OC0B        4
B,7          0,1    OC0A,OC1C  13 - analogRead uses only OC0A

B,5          1      OC1A       11
B,6          1      OC1B       12

H,6          2      OC2B        9
B,4          2      OC2A       10

E,3          3      OC3A        5
E,4          3      OC3B        2
E,5          3      OC3C        3

H,3          4      OC4A        6
H,4          4      OC4B        7
H,5          4      OC4C        8

L,3          5      OC5A       46
L,4          5      OC5B       45
L,5          5      OC5C       44 - analogRead doesn't know about this one.

If this is the case, I was also attempting to manipulate 12 LEDs so that it could so the visual representation of how the frequency is changing (so a binary counter or sweeping LEDs). Where will I put that now since I no longer need this compare match interrupt?

ISR(TIMER1_COMPA_vect) {                             // Interrupt handler. Toggle signalA
  if (toggleA) {
    digitalWrite(signalA, HIGH);
    PORTA = intcount;                                // This code is for the binary counter for the 12 LEDs
    PORTC = intcount >> 4;                           // Additional port registers are shifted by 4 bits
    intcount++;                                      // Increment counter
    toggleA = 0;
  }
  else {
    digitalWrite(signalA, LOW);
    toggleA = 1;
  }
}

I was also attempting to manipulate 12 LEDs so that it could so the visual representation of how the frequency is changing (so a binary counter or sweeping LEDs). Where will I put that now since I no longer need this compare match interrupt?

I would place any visual representation of how the frequency is changing in the analogRead() function which sets the frequency. Setting the frequency and displaying the setting are separate functions from the quadrature signal generation by the timer.

cattledog:
I would place any visual representation of how the frequency is changing in the analogRead() function which sets the frequency. Setting the frequency and displaying the setting are separate functions from the quadrature signal generation by the timer.

My thinking was that for every rising edge of the quadrature signal, it would trigger the LED counter and light up the LEDs in that frequency. Which is why I had used the timer compare match interrupt because then at the same time the signal would rise, it would also increment the LEDs.
I have also altered my code in so that it doesn't need the ISR, but it still changes direction whenever I change the frequency. I have a switch that does that for me (which is similar to your command code).
Also thank you-- you both have been incredibly helpful!

volatile int signalA = 11;                            // Set signal A for pin 9
volatile int signalB = 12;                           // Set signal B for pin 12
const int potPin = A1;                               // Set potentiometer for pin A1
const byte switchPin = 38;                           // Set switch for pin 38
volatile byte switchState = 0;                       // Current state of switchPin
byte changeState = 0;                                // Variable to check to see if switchPin state value has changed
char Command = 'F';

boolean toggleA = 0;                                 // Toggle flag for signal A
boolean toggleB = 0;                                 // Toggle flag for signal B

int value = 0;                                       // Analog to digital value read in by potentiometer
int potval = 0;                                      // Variable to check to see if potentiometer value has changed
int buf[4];                                          // Buffer for potentiometer values
int cumulative = 0;                                  // Variable to hold all current buf values
int bufcount = 0;                                    // Counter for buf
uint16_t intcount = 0;                               // Counter for LEDs
//uint16_t intcount2 = 1000000;


void setup() {
  Serial.begin(9600);
  pinMode(signalA, OUTPUT);                          // Initialize signal pins to be outputs
  pinMode(signalB, OUTPUT);
  pinMode(9, INPUT);


  pinMode(potPin, INPUT);                            // Set potentiometer pin to be input
  pinMode(switchPin, INPUT_PULLUP);                  // The switch pin is an input pulled HIGH by an internal resistor

  DDRA = B11111111;                                  // Set PORTA to outputs
  DDRC = B11111111;                                  // Set PORTA to outputs 

  GTCCR |= 1 << PSRASY; //reset prescaler

  TCCR1A = 0;                                        // Set timer
  TCCR1B = 0;
  TCNT1 = 0;                                         // Set counter to 0. TCNT1 stores the timer 1 counter values

  ICR1 = 199;                                        // Set default ICR1 = [16Mhz / (desired frequency * prescaler)] - 1
  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = (ICR1 - 1) / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle
  TCCR1B |= (1 << CS11);                             // Set prescaler
  // CS10, CS11, CS12 are the clock select bits for Timer 1
  // Each bit corresponds to a prescaler
  // In this case, enabling CS11 will set the prescaler to 8.
//  TIMSK1 |= (1 << OCIE1A) | (1 << OCIE1B);           // Enable Timer Compare Interrupt A & B
  TCCR1A = _BV(COM1A0) | _BV(COM1B0); //Toggle OC1A/OC1B on compare match
  TCCR1B |= (1 << WGM13) | (1 << WGM12);             // CTC mode with ICR1 = Clear timer when the counter reaches the compare match register
  // This will set the two bits of WGM to 14
  // Note: 1 << WGM12 is the same as TCCR1B = 32
//  TIMSK1 |= (1 << OCIE1A);           // Enable Timer Compare Interrupt A & B

}


void loop() {
  switchState = PIND & 0b10000000;                   // Set switchState to only observe digital pin 38
  if (changeState != switchState) {                  // If changeState does not equal the current state of the switchPin
    switchPins();                                    // Call method to change the signal pins
   Serial.println("change: ");
      Serial.println(changeState);

    changeState = switchState;                       // Set changeState to equal the current state of the switchPin
  }
  delay(100);
  readPin();                                         // Read potentiometer pin  
}

void readPin() {
  volatile int temp = analogRead(potPin);            // Analog read from potPin and assigned to value
  temp = temp >> 4;                                  // Shift value by 4 bits to reduce range (1023/16) for smoother transition
  if (bufcount < 4) {                                // If the bufcount is less than 4, have it equal the value of the potPin
    buf[bufcount] = temp;
    cumulative += buf[bufcount];                     // Add and store buf into cumulative
    bufcount++;                                      // Increment bufcount
  }
  else {                                             // If bufcount is now greater than the buf size
    value = cumulative >> 2;                         // value is equal to cumulative/4
    bufcount = 0;                                    // Reset both bufcount and cumulative
    cumulative = 0;
  }
  if (potval - value > 1 || potval - value < -1) {                             // If potval does not equal value, update the frequency
    resetICR(value);
    potval = value;                                  // Set potval to equal value
  }
}

void resetICR(int input) {

  ICR1 = input;   
    TCCR1A = 0;                                        // Set timer
  TCCR1B = 0;
  TCNT1 = 0; 
      
  if(changeState == 128){
  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = OCR1A / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle, toggling signal half a period later
    TCCR1B |= _BV(CS11);//start timer
  }
  else {
  OCR1B = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1A = OCR1B / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle, toggling signal half a period later
    TCCR1B |= _BV(CS11);//start timer
  }

    TCCR1A = _BV(COM1A0) | _BV(COM1B0); //Toggle OC1A/OC1B on compare match
  TCCR1B |= (1 << WGM13) | (1 << WGM12);  
}

void switchPins() {                                  // Change direction of quadrature
  if(changeState == 128){
  OCR1A = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1B = OCR1A / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle, toggling signal half a period later
  TCCR1B |= (1 << CS11);                             // Set prescaler
  Serial.println("Forward");
  }
  else {
  OCR1B = ICR1 - 1;                                  // Set Compare Match Register A to ICR1 at almost 100% duty cycle
  OCR1A = OCR1B / 2;                                 // set Compare Match Register B to OCR1A with 50% duty cycle, toggling signal half a period later
  TCCR1B |= (1 << CS11);                             // Set prescaler
    Serial.println("backward");
  }
}

//ISR(TIMER1_COMPA_vect) {                             // Interrupt handler. Toggle signal
//    PORTA = intcount;                                // This code is for the binary counter for the 12 LEDs
//    PORTC = intcount >> 4;                           // Additional port registers are shifted by 4 bits
//    intcount++;                                      // Increment counter}
//}

Good progress.

I have also altered my code in so that it doesn't need the ISR, but it still changes direction whenever I change the frequency. I have a switch that does that for me (which is similar to your command code).

Are you saying that whenever you call resetICR(value) the direction changes even if you haven't changed the switch on pin 38?

First thing, I would separate the direction change code switchPins() from the frequency change code resetICR(value). You have two different functions responding to two different inputs. There may be an error in your code, and it will be easier to find if the two changes -- frequency and direction are in their own functions.

cattledog:
Are you saying that whenever you call resetICR(value) the direction changes even if you haven't changed the switch on pin 38?

First thing, I would separate the direction change code switchPins() from the frequency change code resetICR(value). You have two different functions responding to two different inputs. There may be an error in your code, and it will be easier to find if the two changes -- frequency and direction are in their own functions.

yes, it seems to still be changing.

I thought they are separate, in that the ICR1 is being altered only in resetICR(). Then, I have to set OCR1A and OCR1B again if I wanted them to have the new ICR1 value. I had it set that way because if the switch is on, then it will keep going forward. If not, it will go backward. Hence, why resetICR is written that way. Unless that's also incorrect and I only need to change a couple of things.

The switchPins follows your command code from before, so it's not changing the ICR1.

I thought they are separate, in that the ICR1 is being altered only in resetICR(). Then, I have to set OCR1A and OCR1B again if I wanted them to have the new ICR1 value. I had it set that way because if the switch is on, then it will keep going forward. If not, it will go backward. Hence, why resetICR is written that way

Ok, I understand.

I'm not certain I understand why you are seeing what you are, but here is some simplified code for the two functions. You were changing some timer settings that did not need to be changed. The serial prints should give you more information.

void resetICR(int input) {

  TCCR1B &= ~(_BV(CS11));//stop timer
  ICR1 = input; //change TOP for frequency
  TCNT1 = 0;//reset counter

  if (changeState == 128) {
    OCR1A = ICR1 - 1;
    OCR1B = OCR1A / 2;
    Serial.println("Forward");
  }
  else {
    OCR1B = ICR1 - 1;
    OCR1A = OCR1B / 2;
    Serial.println("backward");
  }
  TCCR1B |= _BV(CS11);//start timer
}

void switchPins() { // Change direction of quadrature
  
  TCCR1B &= ~(_BV(CS11));//stop timer
  TCNT1 = 0;//reset counter

  if (changeState == 128) {
    OCR1A = ICR1 - 1;                                  
    OCR1B = OCR1A / 2;                                 
    Serial.println("Forward");
  }
  else {
    OCR1B = ICR1 - 1;                                  
    OCR1A = OCR1B / 2;                                                           
    Serial.println("backward");
  }
  TCCR1B |= (1 << CS11); //start timer
}

cattledog:
Ok, I understand.

I'm not certain I understand why you are seeing what you are, but here is some simplified code for the two functions. You were changing some timer settings that did not need to be changed. The serial prints should give you more information.

Unfortunately, it is still changing directions regardless. I was looking at another forum and this person was experiencing the same issues:
https://forum.arduino.cc/index.php?topic=632876.0

They were also trying to change the ICR1, OCR1A, and OCR1B values, however couldn't do so properly so they had to disable the pins first before re-enabling them. I've also attempted this approach just now and I'm just stumped because it's also not working.

But the print statements are printing out the intended output, but the actual signals themselves are not. I thought that setting everything to zero and re-enabling them would work, but to no avail.

Unfortunately, it is still changing directions regardless.

But the print statements are printing out the intended output, but the actual signals themselves are not.

How are you determining the direction? Do you have a quadrature reading program or are you using a scope?

Are you dealing with a first pulse glitch, or an ongoing directional change?

I have a quadrature reading program that indicates whether or not it is going forward or reverse (also tracks the encoder counts for both directions as well). I also have an oscilloscope attached to both of the pins, and they are changing directions.

First pulse glitch, I think.

It is only when I rotate the potentiometer to update the frequency that it changes the direction. It doesn't always change direction, but it does most of the time. So once it changes direction, it will stay in that direction until I try to update the frequency again.