Quadrature signals using Arduino Genuino UNO board

Hi;

I have an Arduino Genuino UNO board. In my project, I need to generate quadrature signals. I am using pins 9,10,11, 12 for this purpose. My requirement is that signal of pin 9 should be in phase difference of 90 degree with pin 11 and signal of pin 10 should be in phase difference of 90 degrees with pin 12. Also pin 9 should have phase difference of 10 degree with 10 and pin 11 should have phase difference of 10 degree with pin 12.

Do you guys have a solution?

Below is the code I have written:

unsigned int InFreq = 0;
unsigned int InShiftFreq = 0;
unsigned int ReFreq = 0;
unsigned int ReShiftFreq =0;
unsigned int FreqtoTest={250,125,62,31,15,7,3};
void setup()
{
int j=0;
pinMode( 9 , OUTPUT ); // Arduino Pin 9 = OCR1A
pinMode( 10 , OUTPUT ); // Arduino Pin 10 = OCR1B
pinMode( 11, OUTPUT );
pinMode( 12, OUTPUT );

//TCCR1A = _BV( COM1A0 ) |_BV( COM1B0 ); // Both outputs in toggle mode
//TCCR1B = _BV( WGM13) | _BV( WGM12); // CTC Waveform Generation Mode
//OCR1A = 0; // Let’s assume initially it is zero, then it toggles to zero
for (j=0;j<7;j++)
{
porttoggle(FreqtoTest[j]);
}
}

// prescaler of 1 will get us 8MHz - 488Hz
// User a higher prescaler for lower freqncies

//#define PRESCALER 1
//#define PRESCALER_BITS 0x01
//#define CLK 16000000UL // Default clock speed is 16MHz on Arduino Uno

/*int setWaveforms( unsigned long freq , int shift )
{
unsigned long clocks_per_toggle = (CLK / freq) / 2; // /2 becuase it takes 2 toggles to make a full wave
ICR1 = clocks_per_toggle;
unsigned long offset_clocks = (clocks_per_toggle * shift) / 180UL;
OCR1B= offset_clocks;
TCCR1B |= _BV( CS11 );

}*/

int porttoggle(unsigned int TimeDelay)
{
int i=0;
InFreq = TimeDelay;
InShiftFreq = TimeDelay/2;
for(i=0;i<100;i++)
{
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
delay(InShiftFreq);
digitalWrite(11,HIGH);
digitalWrite(12, HIGH);
//delay(InShiftFreq);
//delay(InShiftFreq);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
delay(InShiftFreq);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
delay(InShiftFreq);
//delay(InShiftFreq);
}
}

//cycling through some phase shifts at 50Khz

void loop()
{

porttoggle(10);
// setWaveforms( 100 , 90 );
}

Please edit your post to add

[code]and [/code]

around your code so it looks like this...

and

The forum software will eat some of your code and turn it into smileys if you don't.

There's a lot of crap in that which is commented out. Please help us by editing your code before posting it. Just finding where the "frequency" gets set in that code is quite difficult.

You have used the word "freq" or variations of it many times except you are using it as a period. It helps both our understanding if you use the right word to describe the contents of the variable. Long variable names are encouraged - there's no penalty for writing a long name. The compiler changes the variable names into code that the Arduino can understand so it never sees the names you used.

You have delays between only some of your phase transitions. Why are the ones in the middle commented out?

You didn't actually say what the code is doing wrong. You described what you want it to do. What does it actually do?

If I had this requirement, I would not write my own code. The 4-phase system you have described is like a stepper motor. I would use the basic Stepper.h library to generate that output.

Below is the code I have written

Written, or cut and pasted together from other peoples code?

Hi;

Thanks for your advice on the way of writing the code.

The above program I have written is produces a signals of pin 9 and 10 with phase difference 90 but not a quadrature signal (as per the phase difference details I mentioned above w/ pins 9,10,11,12).

I am not good in programming, Can you modify this code or have a program to generate quadrature signals as mentioned above with these 4 pins using Genuino Uno board?

Please edit your post to add code tags.

Maybe you can have a high enough frequency clock signal connected to an interrupt. And each time a falling edge is detected… increment a counter (or various counters).

And depending on the number of counts that have been counted… toggle various outputs on or off to get what you need.

Hi,

If I had to solve this, I would probably jot down on a piece of paper what the signals would look like. An image is worth a 1000 words.

Looking at this image, a brute force way to obtain what you want could be:

unsigned long frequency = 1000;                              //hz
unsigned long period = 1000000 / frequency ;           //us
unsigned long tenDegrees = period/36;                     //us
unsigned long eightyDegrees = tenDegrees * 8;         //us

void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
}

void loop() {
  digitalWrite(12, HIGH)
  delayMicroseconds(tenDegrees);
  digitalWrite(11, HIGH)
  delayMicroseconds(eightyDegrees);
  digitalWrite(10, HIGH)
  delayMicroseconds(tenDegrees);
  digitalWrite(9, HIGH)
  delayMicroseconds(eightyDegrees);
  digitalWrite(12, LOW)
  delayMicroseconds(tenDegrees);
  digitalWrite(11, LOW)
  delayMicroseconds(eightyDegrees);
  digitalWrite(10, LOW)
  delayMicroseconds(tenDegrees);
  digitalWrite(9, LOW)
  delayMicroseconds(eightyDegrees);
}

Of course, the loop part could be reworked, but the code shown above will do the trick.

Note that due to limitations on delayMicroseconds(), you can’t go under 31 Hz. You cannot go beyond 28KHz either, as at this frequency, 10 degrees is 1 microsecond.

EDIT : You can go as down as 2 Hz by replacing:
delayMicroseconds(eightyDegrees);
with
for (int deg = 1 ; deg <= 8 ; deg++)
delayMicroseconds(tenDegrees);

The higher the frequency, the less precise it can be. See the attached graph (this is because microseconds are natural numbers… not reals) .
Between 31 and 165 Hz you are within ± 0,5 Hz
Between 166 and 233 Hz you are within ± 1 Hz
Between 234 and 330 Hz you are within ± 2 Hz
Between 334 and 462 Hz you are within ± 4 Hz
Between 470 and 645 Hz you are within ± 8 Hz
Between 661 and 1157 Hz you are within ± 25 Hz
Between 1207 and 3472 Hz you are within ± 250 Hz
Other avail frequencies are : 3968, 4629, 5555, 6944, 9259, 13888 and 27777 Hz

If you want precise frequencies, you will have to go with Southpark’s suggestion. Then you could be right on the ball at well better than 100 khz.

Jacques

Southpark:
Maybe you can have a high enough frequency clock signal connected to an interrupt. And each time a falling edge is detected..... increment a counter (or various counters).

And depending on the number of counts that have been counted..... toggle various outputs on or off to get what you need.

Southpark;

Do you have a code for that, which I shall try with? I don't get to understand it clearly.

void loop(){
  static byte counter=0;
  if(counter==0) doFirstQuadrant();
  if(counter==1) doSecondQuadrant();
  if(counter==2) doThirdQuadrant();
  if(counter==3) doFourthQuadrant();
  counter++;
  if(counter>=4) counter=0;
  delay(delayTime);
}

I can't see any specification for frequency other than the original code (still without code tags) so the delay() is rather crude but still functional for the given frequencies.

Do you have a code for that, which I shall try with? I don't get to understand it clearly.

If you decide to go with an external clock, you will have to decide what clock you will use and look at the spec sheet before you start thinking about code.

I can't see any specification for frequency other than the original code (still without code tags) so the delay() is rather crude but still functional for the given frequencies.

The highest frequency mentionned is 250 Hz. That means a period of 4 ms. Signals have to be phase shifted by 10 degrees, giving 0,1111 millisecond (4 ms / 36). That is why I suggested to go with delayMicrosecond().

delayMicrosecond( 111) => 250,250Hz
delayMicrosecond( 222) => 125,125Hz
delayMicrosecond( 448) => 62,003Hz
delayMicrosecond( 896) => 31,002Hz
delayMicrosecond(1852) => 14,999Hz
delayMicrosecond(3968) => 7,000Hz
delayMicrosecond(9259) => 3,000Hz

We would have to remove 2 microseconds to those figures to take digitalWrite()'s execute time into account.