Skip to main content
added 534 characters in body
Source Link
bigjosh
  • 1.6k
  • 10
  • 13

Wow, that turned out to be way harder than I expected. It is very hard to do cleanly on the AVR timer. But I was able to come up with this working function, which I think is what you are looking for...

// freq_hz is frequency in hertz from 122 to 4,000,000
// shift_deg is phase shift between output A and output B in degrees (values outside -180 to +180 are normalized)

// Note that at frequencies above 44KHz you will loose precision on phase shift. At 4Mhz, everything is rounded to just 0 or +/-90 degrees.
// Note that all timing happens in 1/16Mhz increments, so frequencies that do not land on integer multipules of that will be aproximiate. 
// Use startWaveforms() directly for more precise control. 

void startQuadrature( unsigned long freq_hz , int shift_deg  );

It can glitch at start-up, shutdown, and changes in speed and direction... but so can a motor encoder so I guess that is ok. It would be possible to create a glitch-free version but more work.

Github repo here... https://github.com/bigjosh/Quadrature

So, to simulate a motor going forward with 50KHz pulse rate, you would use something like...

startQuadrature( 50000 , +90);

...and the same pulse rate going backwards would be...

startQuadrature( 50000 , -90);

Do note that if you connect an Arduino UNO output pin to a Raspberry Pi input pin that it will likely damage the Pi. This is because the UNO outputs 5 volts for a "1" signal, but the Pi can only tolerate a maximum 3.3V on any pin. You can google "5V 3.3V level shifting" for solutions to this problem.

Wow, that turned out to be way harder than I expected. It is very hard to do cleanly on the AVR timer. But I was able to come up with this working function, which I think is what you are looking for...

// freq_hz is frequency in hertz from 122 to 4,000,000
// shift_deg is phase shift between output A and output B in degrees (values outside -180 to +180 are normalized)

// Note that at frequencies above 44KHz you will loose precision on phase shift. At 4Mhz, everything is rounded to just 0 or +/-90 degrees.
// Note that all timing happens in 1/16Mhz increments, so frequencies that do not land on integer multipules of that will be aproximiate. 
// Use startWaveforms() directly for more precise control. 

void startQuadrature( unsigned long freq_hz , int shift_deg  );

It can glitch at start-up, shutdown, and changes in speed and direction... but so can a motor encoder so I guess that is ok. It would be possible to create a glitch-free version but more work.

Github repo here... https://github.com/bigjosh/Quadrature

Wow, that turned out to be way harder than I expected. It is very hard to do cleanly on the AVR timer. But I was able to come up with this working function, which I think is what you are looking for...

// freq_hz is frequency in hertz from 122 to 4,000,000
// shift_deg is phase shift between output A and output B in degrees (values outside -180 to +180 are normalized)

// Note that at frequencies above 44KHz you will loose precision on phase shift. At 4Mhz, everything is rounded to just 0 or +/-90 degrees.
// Note that all timing happens in 1/16Mhz increments, so frequencies that do not land on integer multipules of that will be aproximiate. 
// Use startWaveforms() directly for more precise control. 

void startQuadrature( unsigned long freq_hz , int shift_deg  );

It can glitch at start-up, shutdown, and changes in speed and direction... but so can a motor encoder so I guess that is ok. It would be possible to create a glitch-free version but more work.

Github repo here... https://github.com/bigjosh/Quadrature

So, to simulate a motor going forward with 50KHz pulse rate, you would use something like...

startQuadrature( 50000 , +90);

...and the same pulse rate going backwards would be...

startQuadrature( 50000 , -90);

Do note that if you connect an Arduino UNO output pin to a Raspberry Pi input pin that it will likely damage the Pi. This is because the UNO outputs 5 volts for a "1" signal, but the Pi can only tolerate a maximum 3.3V on any pin. You can google "5V 3.3V level shifting" for solutions to this problem.

Source Link
bigjosh
  • 1.6k
  • 10
  • 13

Wow, that turned out to be way harder than I expected. It is very hard to do cleanly on the AVR timer. But I was able to come up with this working function, which I think is what you are looking for...

// freq_hz is frequency in hertz from 122 to 4,000,000
// shift_deg is phase shift between output A and output B in degrees (values outside -180 to +180 are normalized)

// Note that at frequencies above 44KHz you will loose precision on phase shift. At 4Mhz, everything is rounded to just 0 or +/-90 degrees.
// Note that all timing happens in 1/16Mhz increments, so frequencies that do not land on integer multipules of that will be aproximiate. 
// Use startWaveforms() directly for more precise control. 

void startQuadrature( unsigned long freq_hz , int shift_deg  );

It can glitch at start-up, shutdown, and changes in speed and direction... but so can a motor encoder so I guess that is ok. It would be possible to create a glitch-free version but more work.

Github repo here... https://github.com/bigjosh/Quadrature