Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Reading BLDC Hall Sensors using interrupts

  1. #1
    Junior Member
    Join Date
    Mar 2014
    Posts
    12

    Reading BLDC Hall Sensors using interrupts

    Hi all,
    It's been a while since I've posted on this forum, but I need some advice on a Teensy project I'm doing. I have a Brushless motor with 3 Hall sensors. The motor has 7 pole pairs that each are being read by the Hall sensors at 5000 rpm. Controlling the motor is done using a separate motor controller, but I need to convert the Hall Sensor input into an A/B quadrature Encoder signal for another device. My first idea was using the Encoder library for Teensy, but that only supports two inputs. I then figured that I'll do a simplistic approach using Interrupts and I came up with the code below.

    It works quite well. I can get direction and position out, but even at moderate speeds, I'm loosing some "steps" so the position on the motor controller will differ from the one on the Teensy. I could of course throw a Teensy 4.0 at it and hope that the extra speed solves the issue, but I can't help but think that there are others that have done similar things and come up with a better solution? I'd love to hear how others have solved similar problems.

    Code:
    #define HALLPIN1 10
    #define HALLPIN2 11
    #define HALLPIN3 12
    
    volatile unsigned int lastPin = 0;
    volatile signed int dir = 0;
    signed int dirDisplay = 0;
    volatile signed long pos = 0;
    volatile signed long lastChange = 0;
    signed long prevPos = 0;
    
    void setup() {
      pinMode(HALLPIN1, INPUT);
      pinMode(HALLPIN2, INPUT);
      pinMode(HALLPIN3, INPUT);
      
      attachInterrupt(digitalPinToInterrupt( HALLPIN1 ), hall1, CHANGE);
      attachInterrupt(digitalPinToInterrupt( HALLPIN2 ), hall2, CHANGE);
      attachInterrupt(digitalPinToInterrupt( HALLPIN3 ), hall3, CHANGE);
    }
    
    void loop() {
      // nada
    }
    
    void hall1() {
      if( lastPin == HALLPIN3 )
      {
        dir = -1; // backward
      }
      else if( lastPin == HALLPIN2 )
      {
        dir = 1; // forward
      }
      pos += dir;
      lastPin = HALLPIN1;
    }
    
    void hall2() {
      if( lastPin == HALLPIN1 )
      {
        dir = -1;
      }
      else if( lastPin == HALLPIN3 )
      {
        dir = 1;
      }
      pos += dir;
      lastPin = HALLPIN2;
    }
    
    void hall3() {
      if( lastPin == HALLPIN2 )
      {
        dir = -1;
      }
      else if( lastPin == HALLPIN1 )
      {
        dir = 1;
      }
      pos += dir;
      lastPin = HALLPIN3;
    }
    Last edited by jensa; 03-23-2020 at 11:33 PM.

  2. #2
    Member
    Join Date
    Feb 2018
    Location
    Corvallis, OR
    Posts
    60
    Your sample code doesn't show anything using the dir and pos values. I think it is that missing code that is your problem. The default priority for attachInterrupt is 128, in the middle of the priority range. Other things such as the systick, USB, SDIO and timer drivers may have higher priority and be blocking your pin interrupts long enough to cause problems. At 2400 RPM (40 RPS) , you are getting 3 interrupts every 25 milliseconds. If equally spaced, that is an interrupt each 8.3mSec.

    You can search the forum for "attachInterrupt priority" and find some information on how to increase the priority of your pin interrupts. That might solve your problem with missed pulses.

  3. #3
    Junior Member
    Join Date
    Mar 2014
    Posts
    12
    Thanks @mbogerson! Those posts was quite a dense read, but from what I gathered it boils down to adding this one line to the setup-method (given that the pins I use are on the C-port:

    Code:
    NVIC_SET_PRIORITY(IRQ_PORTC, 0);
    Using 0 gave the better results, but it was not perfect still. I initially tried using priority 48 on my Teensy 3.2 and that was practically no difference. A friend suggested using the timers, so I'll look into that next.

  4. #4
    Junior Member
    Join Date
    Mar 2014
    Posts
    12
    The solution became to use the standard Encoder class for Teensy and just ignore one of the three phases in the Hall sensor signal. This looses precision, but solves the problem elegantly as it produces the A&B signals I need. If the result is multiplied with 1.5, I'll get the same count as the Epos4 motor driver also and it's 100% identical to the Teensy

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •