# Problem to declare the one-channel encoder of SparkFun gimbal 3-Phase BLDC motor?

**URL:** <https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621>\
**Category:** Robotics\
**Created:** [September 28, 2026, 4:34am UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621 "2026-09-28T04:34:56Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![B](https://avatars.discourse-cdn.com/v4/letter/b/ee7513/32.png) [@B](https://community.sparkfun.com/u/B)\
**Post date:** [September 28, 2026, 4:34am UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/1 "2026-09-28T04:34:56Z")

</div>

Hello. I built a SimpleFOC PID-control code for two SparkFun gimbal 12V 3-Phase BLDC motors with the encoders AS5048A [Gimbal Motor with Encoder - 12V, 467RPM - SparkFun Electronics](https://www.sparkfun.com/gimbal-motor-with-encoder-12v-587rpm.html) based on the one-motor example code [Position Control example | Arduino-FOC](https://docs.simplefoc.com/position_control_example) .  
However, there is the following problem. The example code uses _**Encoder encoder = Encoder(A, B, number\_of\_Pulses\_Per\_Rotation)**_ to declare an encoder. _ **A** _ and _ **B** _ are two pin numbers for two channels of an encoder. The gimbal SparkFun motor exploits the one-channel encoder AS5048A. The class _ **Encoder** _ works with two-channel encoders. Setting just one pin number in the encoder declaration statement results into the error. Could someone please recommend how to declare the one-channel encoder in the SimpleFOC PID-control code? Thank you.

---

<div class="post-metadata">

**Author:** ![TS-Russell](https://yyz1.discourse-cdn.com/sparkfun/user_avatar/community.sparkfun.com/ts-russell/32/6092_2.png) [@TS-Russell](https://community.sparkfun.com/u/TS-Russell)\
**Post date:** [September 30, 2026, 2:01am UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/2 "2026-09-30T02:01:10Z")

</div>

Instead of `Encoder` use the `MagneticSensorSPI` class

---

<div class="post-metadata">

**Author:** ![B](https://avatars.discourse-cdn.com/v4/letter/b/ee7513/32.png) [@B](https://community.sparkfun.com/u/B)\
**Post date:** [September 30, 2026, 4:52pm UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/3 "2026-09-30T16:52:15Z")

</div>

Thank you, TS-Russell. If use the _ **MagneticSensorSPI** _ class, we need to use the SPI pins of the encoder AS5048A. We already connected the encoder by using its PWM pins. If we used the SPI pins, we would need to rewire the encoder. In between, its SPI pins (too small) are not easy to solder.

I came up with another solution. The class _ **MagneticSensorPWM** _ can be used with the encoder PWM pins (one channel pin, VDD. GND). In the code, the encoder declaration is _**MagneticSensorPWM encoder = MagneticSensorPWM(~A12, minimal\_pulse\_microseconds, maximal\_pulse\_microseconds)**_ if SparkFun RedBoard Artemis ATP is used. Based on the SimpleFOC webpage “PWM output Magnetic sensor setup” [Magnetic sensor PWM | Arduino-FOC](https://docs.simplefoc.com/magnetic_sensor_pwm) , the argument _ **minimal\_pulse\_microseconds** _ (or _ **min\_raw\_count** _) represents the shortest expected length of the high-state digital pulse corresponding to a 0 degree absolute angle position. However, the calibration of the values of the _ **minimal\_pulse\_microseconds** _ and the _ **maximal\_pulse\_microseconds** _ is needed because magnetic encoders do not start pulse width at 0 microsecond for the 0 degree. They begin pulse with a brief initialization/synchronization period in according to: [MagneticSensorPWM - developement - SimpleFOC Community](https://community.simplefoc.com/t/magneticsensorpwm/868) .

For the encoder AS5048A, the minimal time the pulse is HIGH is typically from 4 us to 12 us, even if its magnet is exactly at the 0 degree. The encoder AS5048A maximal pulse time is around 4119 us. However, the calibration is required to avoid the rotors’ “jumps”. If somebody has any other useful info, please comment. Thank you.

---

<div class="post-metadata">

**Author:** ![TS-Russell](https://yyz1.discourse-cdn.com/sparkfun/user_avatar/community.sparkfun.com/ts-russell/32/6092_2.png) [@TS-Russell](https://community.sparkfun.com/u/TS-Russell)\
**Post date:** [September 30, 2026, 10:47pm UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/4 "2026-09-30T22:47:03Z")

</div>

Ah, sorry - brain fart…I meant PWM 🙂

---

<div class="post-metadata">

**Author:** ![B](https://avatars.discourse-cdn.com/v4/letter/b/ee7513/32.png) [@B](https://community.sparkfun.com/u/B)\
**Post date:** [October 3, 2026, 1:51am UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/6 "2026-10-03T01:51:28Z")

</div>

Hello. I built a code to read and print the widths (time) of minimal and maximal pulses of PWM channels of two AS5048A encoders connected to the SparkFun RedBoard Artemis ATP microcontroller board analog pins. The first encoder PWM wire is connected to the pin ~A12. The second encoder PWM wire is connected to the pin ~A13. When my code was executed, the readings of the pulses sometimes jumped to some thousand microseconds. May somebody please specify why such jumps could happen? Maybe something is wrong with the RedBoard Artemis ATP board or with the code? Here is the code:

/\* The following code to find the values of min\_pulse\_us and max\_pulse\_us  
for twp AS5048A encoders based on the example code published here:

> **[Magnetic sensor PWM](https://docs.simplefoc.com/magnetic_sensor_pwm)**
>
> Arduino Simple Field Oriented Control (FOC) library .

NOTE: Pulse width even at zero degree is not equal to zero  
\*/  
//#include \<SimpleFOC.h\>  
//#include \<Arduino.h\>

const int PWM\_pin\_encoder1 = A12; // Connect to the AS5048A encoder #1 PWM pin  
const int PWM\_pin\_encoder2 = A13; // Connect to the AS5048A encoder #2 PWM pin  
unsigned long Min\_pulse\_encoder1\_us = 100; // Encoder 1 - state minimal pulse width higher than the possible one  
unsigned long Max\_pulse\_encoder1\_us = 100000; // Encoder 1 - state maximal pulse width higher than the possible one  
unsigned long Min\_pulse\_encoder2\_us = 100; // Encoder 2 - state minimal pulse width higher than the possible one  
unsigned long Max\_pulse\_encoder2\_us = 100000; // Encoder 2 - state maximal pulse width higher than the possible one

void setup() {  
pinMode(PWM\_pin\_encoder1, INPUT);  
pinMode(PWM\_pin\_encoder2, INPUT);  
Serial.begin(115200);  
Serial.println(“Rotate both AS5048A encoders 360 degrees to find Min/Max Pulse Values”);  
delay(10);  
}  
// Make loop to read and print Max/Min pulse time of Encoder 1 and Encoder 2  
void loop() {  
// Read the HIGH state pulse width in microseconds  
// Timeout set to 1000000us to capture low/high safely  
unsigned long currentPulse1 = pulseIn(PWM\_pin\_encoder1, HIGH, 1000000);  
unsigned long currentPulse2 = pulseIn(PWM\_pin\_encoder2, HIGH, 1000000);

if (currentPulse1 \> 0 && currentPulse2 \> 0) {  
bool updated = false;

// Reject outliers and look for absolute bounds  
if (currentPulse1 \< Min\_pulse\_encoder1\_us && currentPulse1 \> 0) {  
Min\_pulse\_encoder1\_us = currentPulse1;  
updated = true;  
}  
if (currentPulse1 \> Min\_pulse\_encoder1\_us && currentPulse1 \< 100000) {  
Max\_pulse\_encoder1\_us = currentPulse1;  
updated = true;  
}  
// Reject outliers and look for absolute bounds  
if (currentPulse2 \< Min\_pulse\_encoder2\_us && currentPulse2 \> 0) {  
Min\_pulse\_encoder2\_us = currentPulse2;  
updated = true;  
}  
if (currentPulse2 \> Min\_pulse\_encoder2\_us && currentPulse2 \< 100000) {  
Max\_pulse\_encoder2\_us = currentPulse2;  
updated = true;  
}  
// Print Max and Min Pulse Time of Encoder #1 and Encoder #2  
if (updated) {  
Serial.print("Encoder #1 → Min Pulse: “);  
Serial.print(Min\_pulse\_encoder1\_us);  
Serial.print(” us | Max Pulse: “);  
Serial.print(Max\_pulse\_encoder1\_us);  
Serial.print(” us ");  
Serial.print(“Encoder #2 → Min Pulse: “);  
Serial.print(Min\_pulse\_encoder2\_us);  
Serial.print(” us | Max Pulse: “);  
Serial.print(Max\_pulse\_encoder2\_us);  
Serial.print(” us\n”);

delay(1000);  
}

}  
}

Thank you.

---

<div class="post-metadata">

**Author:** ![PaulZC](https://yyz1.discourse-cdn.com/sparkfun/user_avatar/community.sparkfun.com/paulzc/32/67_2.png) [@PaulZC](https://community.sparkfun.com/u/PaulZC)\
**Post date:** [October 5, 2026, 5:54am UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/7 "2026-10-05T05:54:13Z")

</div>

Hi Boris ( @B ),

Please try:

In your global code:

```auto
unsigned long Min_pulse_encoder1_us = 100000; // Encoder 1 Minimum - set to a large value initially
unsigned long Max_pulse_encoder1_us = 0; // Encoder 1 Maximum - set to zero initially
unsigned long Min_pulse_encoder2_us = 100000; // Encoder 2 Minimum - set to a large value initially
unsigned long Max_pulse_encoder2_us = 0; // Encoder 2 - Maximum set to zero initially

```

Then, in your `loop()`:

```auto
if (currentPulse1 < Min_pulse_encoder1_us && currentPulse1 > 0) {
Min_pulse_encoder1_us = currentPulse1; // Update the Encoder 1 minimum
updated = true;
}
if (currentPulse1 > Max_pulse_encoder1_us && currentPulse1 > 0) {
Max_pulse_encoder1_us = currentPulse1; // Update the Encoder 1 maximum
updated = true;
}
if (currentPulse2 < Min_pulse_encoder2_us && currentPulse2 > 0) {
Min_pulse_encoder2_us = currentPulse2; // Update the Encoder 2 minimum
updated = true;
}
if (currentPulse2 > Max_pulse_encoder2_us && currentPulse2 > 0) {
Max_pulse_encoder2_us = currentPulse2;
updated = true;
}

```

I hope this helps,  
Paul

---

<div class="post-metadata">

**Author:** ![B](https://avatars.discourse-cdn.com/v4/letter/b/ee7513/32.png) [@B](https://community.sparkfun.com/u/B)\
**Post date:** [October 5, 2026, 9:26pm UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/8 "2026-10-05T21:26:43Z")

</div>

Thank you so much, PaulZC. We have just used an oscilloscope to find min/max PWM pulse widths. The first encoder widths are 14us/936us. The second encoder widths are 14us/896us. By the way, they are almost the same that I got by using my code. Just sporadic pulse jumps make me worry. If there can happen longer widths while rotating the motors, what can cause such longer pulse widths that happen from time to time? I just fear that they can disturb the proper PID-control. Thank you.

---

<div class="post-metadata">

**Author:** ![PaulZC](https://yyz1.discourse-cdn.com/sparkfun/user_avatar/community.sparkfun.com/paulzc/32/67_2.png) [@PaulZC](https://community.sparkfun.com/u/PaulZC)\
**Post date:** [October 6, 2026, 5:29am UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/9 "2026-10-06T05:29:33Z")

</div>

Hi @B ,

Are these longer pulses real? Have you seen them on the oscilloscope? Or are they being detected by the code only? If they are only detected by the code then it is probably just the code missing a pulse finish/start and reporting a “double” pulse length?

The solution may be to: use interrupts to detect the pulse edges and calculate the pulse width; and add a filter in your code which rejects any “illegal” pulse widths - longer than ~1ms.

I hope this helps,  
Paul

---

<div class="post-metadata">

**Author:** ![B](https://avatars.discourse-cdn.com/v4/letter/b/ee7513/32.png) [@B](https://community.sparkfun.com/u/B)\
**Post date:** [October 7, 2026, 4:47am UTC](https://community.sparkfun.com/t/problem-to-declare-the-one-channel-encoder-of-sparkfun-gimbal-3-phase-bldc-motor/69621/10 "2026-10-07T04:47:20Z")

</div>

Thank you, PaulZC. An oscilloscope gave square waves. Shrinks happened while we checked the second encoder. However, they might happen because I moved the rotor improperly sometimes.

You suggested to reject “illegal” pulse widths by setting the range in code. However, doing so does not remove a physical reason of their existence. If it works out to make the motors work as needed, then it goes.
