0
\$\begingroup\$

I'm looking to emulate an encoder signal using an Arduino microcontroller (Seeed Xiao, SAMD21 Cortex M0+).

The following works but locks up the main thread with delays. The frequency of pulses isn't critical, but around 100 kHz to 1 MHz is preferred.

kPulseDelayMicroSeconds = 1;
pulses = 10000;
for (int i; i < pulses; i++)
{
 delayMicroseconds(kPulseDelayMicroSeconds);
 digitalWrite(kEncoderAPin, HIGH);
 delayMicroseconds(kPulseDelayMicroSeconds);
 digitalWrite(kEncoderBPin, HIGH);
 delayMicroseconds(kPulseDelayMicroSeconds);
 digitalWrite(kEncoderAPin, LOW);
 delayMicroseconds(kPulseDelayMicroSeconds);
 digitalWrite(kEncoderBPin, LOW);
}

What's a good way of running this in its own "thread"?

This is what I came up with so far.

static const int kEncoderForwardPulseSequence[4][2] =
 {{1, 0}, {1, 1}, {0, 1}, {0, 0}};
static const int kEncoderReversePulseSequence[4][2] =
 {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
uint8_t _encoder_sequence_index = 0;
int32_t _pulses_to_send = 1000;
void ISR()
{
 if (_pulses_to_send != 0)
 {
 if (_pulses_to_send < 0)
 {
 digitalWrite(kEncoderAPin,
 kEncoderReversePulseSequence[_encoder_sequence_index][0]);
 digitalWrite(kEncoderBPin,
 kEncoderReversePulseSequence[_encoder_sequence_index][1]);
 }
 else 
 {
 digitalWrite(kEncoderAPin,
 kEncoderForwardPulseSequence[_encoder_sequence_index][0]);
 digitalWrite(kEncoderBPin,
 kEncoderForwardPulseSequence[_encoder_sequence_index][1]);
 }
 _encoder_sequence_index = (_encoder_sequence_index + 1) % 4;
 if (_encoder_sequence_index == 0)
 {
 _pulses_to_send = _pulses_to_send - sgn(_pulses_to_send);
 }
 }
}
vu2nan
19.7k1 gold badge18 silver badges51 bronze badges
asked Oct 19, 2021 at 0:28
\$\endgroup\$
5
  • 5
    \$\begingroup\$ You should use a timer to create an ISR which fires at a regular interval. Inside that, update the outputs according to a table. You would iterate through that table to simulate encoder motion. \$\endgroup\$ Commented Oct 19, 2021 at 0:39
  • 1
    \$\begingroup\$ @Drew you should make your comment an answer imho \$\endgroup\$ Commented Oct 19, 2021 at 2:33
  • 1
    \$\begingroup\$ I just don't have the time to write it up in detail rn. \$\endgroup\$ Commented Oct 19, 2021 at 3:23
  • \$\begingroup\$ did you try analogWrite? it is PWM. arduino.cc/reference/en/language/functions/analog-io/… \$\endgroup\$ Commented Oct 19, 2021 at 5:35
  • \$\begingroup\$ Wasp, your TC and TCC appear to be pretty powerful peripherals. You probably could just set them up and let them just do the work for you. They will do it with precision. The TCC, in particular, can generate a synchronized bit pattern across the waveform output pins according to the documentation in section 31.1. You can also "bit bang" these, of course, and just use an interval timer. But given the speed and the desire for emulation, I'd just use the TCC and be done with it and move on with the rest of your coding. \$\endgroup\$ Commented Oct 19, 2021 at 5:53

1 Answer 1

1
\$\begingroup\$
setup()
{
 digitalWrite(A, HIGH);
 digitalWrite(B, LOW);
}
 
void ISR()
{
 static count = 1;
 if(count == 1)
 {
 digitalWrite(A, LOW);
 count = 2;
 }
 else if (count == 2)
 {
 digitalWrite(B, HIGH);
 count = 3;
 }
 else if (count == 3)
 {
 digitalWrite(A, HIGH);
 count = 4;
 }
 else if (count == 4)
 {
 digitalWrite(B, LOW);
 count = 1;
 }
}
answered Oct 19, 2021 at 20:39
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.