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;
}
}
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?
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.
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 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.
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}
//}
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.
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.
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.
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.