Running a BLDC motor using Basic

General discussion on mikroBasic for dsPIC30/33 and PIC24.
Post Reply
Author
Message
p.erasmus
Posts: 3391
Joined: 05 Mar 2009 10:28

Running a BLDC motor using Basic

#1 Post by p.erasmus » 11 Aug 2009 20:37

The Following code shows how to run a Brushless motor with the Basic compiler ,You can down load the Application note AN957 from Microchip
it explains all the basics of using adspIC to run a BLDC motor ,However the Code is in C (C18 from Microchip) I have ported it to Basic.

Note : The code is not optimized for speed and the programming style is not the optimum as the Idea is to keep it simple to show how to run a motor and not intended to comply to high Code standards,
The PID close loop the user can try to implement using this code as a Start template

The Initialzation Code

Code: Select all

'************************************************************
module Init
'**************************************************************
'Constants
'************************************************************
const FCY =  20000000    '20Mips XT 10Mhz PLL8
const FPWM = 20000       'Switch Frequency 20Khz
Const PolePairs = 5      'Number of motor pole pairs
const ADIE  = 11         'AD Interrupt enable bit
const ADIF  = 11         'AD Int Flag bit
const ADON  = 15         'Swithch ADON Bit
const CNIF  = 15         'CN Int Flag
const CNIE  = 15         'CN Int Enable bit
const T3ON  = 15         'Timer3 ON Bit
'************************************************************
'Variables
'************************************************************
 Dim StateLowTableClk as word[8]
 Dim StateLowTableAntiClk as word[8]
 Dim RunLedCount as Byte
 Dim PI_Tick as Byte
 Dim PoleCount as Byte
'************************************************************
'Control Flags as a Structure of Bits (BitField)
'************************************************************
 structure Flags
  Dim Flag_StartMotor as Boolean
  Dim Flag_MotorIsRunning as Boolean
  Dim Flag_CalcSpeed as Boolean
  Dim Flag_CalcDutyCycle as Boolean
  end structure
 Dim Flags as Flags   
'************************************************************
'Implementation
'************************************************************
implements
'************************************************************
sub procedure Init ()
 '************************************************************
 'Configure Timer 1 interrupt
 '************************************************************
     TRISC.13 = 1      'RC13 as input stop Button
     TRISD.0 = 1       'RD0 input for run Button
     TRISD.01 = 0
     IEC0.03 = 1        'T1 INT On
     IPC0.14 = 0        'T1 Ip 4
     IPC0.13 = 0
     IPC0.12 = 1
     IFS0.03 = 0        'T1IF Clear
     PR1 =  2500
     T1CON = $A010
 '***************************************
 'Clear Variables on Start up
 '***************************************
     PI_Tick = 0
     RunLedCount = 0
     Flags.Flag_StartMotor = 0
     Flags.Flag_CalcDutyCycle = 0
     Flags.Flag_MotorIsRunning  = 0
     PoleCount = 0     
end sub
'************************************************************
'Initialize the Motor Control PWM Port
'************************************************************
sub procedure Init_MCPWM()
     TRISE = $FFC0          'PWM Pins as output
     PTPER = (FCY/FPWM) -1  'Set the PWM period register
     PWMCON1 = $700         'Disable PWM module
     OVDCON = $0            'allow control over OVDCON
     PDC1 = 100
     PDC2 = 100             'initialize DC register to 100
     PDC3 = 100
     SEVTCMP = PTPER        'ADC to trigger every new PWM cycle
     PWMCON2 = $F00         '16 PWM value
     PTCON = $8000          'Enable MCPWM module
'***********************************************************
'Load the switch sequence in table to MCPWM to fit Hall values
'Clockwise Direction
'************************************************************
    StateLowTableClk[0] = $0
    StateLowTableClk[1] = $210
    StateLowTableClk[2] = $2004
    StateLowTableClk[3] = $204
    StateLowTableClk[4] = $801
    StateLowTableClk[5] = $810
    StateLowTableClk[6] = $2001
    StateLowTableClk[7] = $0
'************************************************************
'Load the switch sequence in table to MCPWM to fit Hall values
'Anti Clockwise Direction
'************************************************************
    StateLowTableAntiClk[0] = $0
    StateLowTableAntiClk[1] = $2001
    StateLowTableAntiClk[2] = $810
    StateLowTableAntiClk[3] = $801
    StateLowTableAntiClk[4] = $204
    StateLowTableAntiClk[5] = $2004
    StateLowTableAntiClk[6] = $210
    StateLowTableAntiClk[7] = $0
end sub
'************************************************************
'Initializes the AD converter Module
'************************************************************
sub procedure Init_ADC ()
   ADPCFG = $FFF8           'ALL PORTB pins Digital RB0-RB2 ANA
   ADCON1 = $0064           'PWM Starts conversion
   ADCON2 = $0200           'Simultanuos sample 4 Channels
   ADCHS  = $0002           'RB2 = AN2 Pottie
   ADCON3 = $0080           'Tad internal RC 4usec
   IFS0.ADIF = 0            'Clear Int Flag
   IEC0.ADIE = 1            'Enable AD interrupt
   ADCON1.ADON = 1          'Enable AD converter

end sub
'************************************************************
'Initialize the CN Pins for Hall sensor state change
'************************************************************
sub procedure Int_CNpins ()
      CNEN1 = $E0           'CN5,6 and 7 enable
      IFS0.CNIF = 0         'Clear Int Flag
      IEC0.CNIE = 1         'Enable CN Interrupt
end sub
'************************************************************
'Initialize Timer 3 used for Speed calculation
'************************************************************
sub procedure Init_T3()
    T3CON = $0030            'Internal clock Tcy/256
    TMR3 = 0                 'Clear the Timer
    PR3 = $FFFF              'load max Time Frame
    T3CON.T3ON = 1
end sub

end.

'************************************************************
Interrupt Service Routines (ISR)

Code: Select all

'************************************************************
module Interrupts
'************************************************************
 'INTERRUPT SERVICE ROUTINES
'************************************************************
const Index = 1
'************************************************************
 Dim HallValue as Byte
 Dim SetSpeed as Word
 Dim Timer3avg as Word
 Dim Timer3Value as Word

 '************************************************************
implements
 '************************************************************
 'Timer 1 Interrupt
 '************************************************************
sub procedure Timer1Int org $1A
   IFS0 = IFS0 and $FFF7
   PI_Tick = PI_Tick +1
   RunLedCount = RunLedCount +1
   if PI_Tick = 40 Then
     Flags.Flag_CalcDutyCycle = 1
     PI_Tick = 0
     end if
   if (RunLedCount = 250) Then
       LATD.01 = LATD.01 Xor 1
       RunLedCount = 0
    end if
end sub
'************************************************************
'ADC Interrupt
'************************************************************
sub procedure ADCInt org $2A
    IFS0.ADIF = 0         'Clear ADC int Flag
    SetSpeed = ADCBUF0    'Read ADC buffer
end sub
'************************************************************
'Change Notification Interrupt(Hallsensor State)
'Select next Step sequence to drive 3 Phase Bridge
'************************************************************
sub procedure CNInt org $32
    IFS0.CNIF = 0    'Clear Int Flag
    HallValue = PORTB and $38
    HallValue = HallValue >> 3
    OVDCON =  StateLowTableClk[HallValue]
    if(HallValue = Index) Then
       PoleCount = PoleCount +1
    if( PoleCount = PolePairs) then
        Timer3Value = TMR3        ' 1 mechanical Rev Completed read Timer
        TMR3 = 0
        Timer3avg = ((Timer3avg + Timer3Value) >>1)
        PoleCount = 0
        Flags.Flag_CalcSpeed = 1
    end if
    end if
end sub
end.
'************************************************************
The Main Code and Stae machine

Code: Select all

'************************************************************
program Bldc_BlockCommutation
'************************************************************
' This code Run the Hurst 24V BLDC motor in Close Loop
'Block Commutation.
'Ported From C18 code to mikroBasic
'As per Microchip Application Note AN957
'Device dsPIC4012 or any dspIC with Motor Control PWM Port
'************************************************************
 include "Init"
 include "Interrupts"
 '************************************************************
 'symbols
 '************************************************************
  'constants
 '************************************************************
 const SpeedFactor = 1.949
 const Timer3Const = 0.0000128
 '************************************************************
 'StateMachine Definitions
 '************************************************************
 const StartMotor = 1
 const RunContinious = 2
 const ErrorState  = 3
 Const StopMotor = 4

 '************************************************************
 'Variables
 '*****************************************************************
 Dim State as Byte
 Dim ActualSpeed as Word
 Dim DesiredSpeed as Word
 Dim CapturedTime as float
 '************************************************************
 ' Structures
 '************************************************************
 '************************************************************
 'Procedures
 '************************************************************
 sub procedure CalcSpeed ()
       CapturedTime = float(Timer3avg )* Timer3Const
       CapturedTime = (pow(CapturedTime ,-1)* float(60) )
       ActualSpeed =  word(CapturedTime)
 end sub
'******************************************************************
 sub function CalcDutyCycle(Dim SetSpeed as word,Dim SpeedFactor
  as real) as real
  result =  real(SetSpeed) * SpeedFactor
 end sub

'***********************************************************
'Main Program
'***********************************************************
main:
'***********************************************************
'Configure microController
'***********************************************************
      Init ()
      Init_MCPWM()
      Init_ADC ()
      Int_CNpins ()
      Init_T3()
      State = 0
while True
'************************************************************
'Check if start button is pressed
'************************************************************
   if Button(PORTD,0, 100, 0)= 1   then
     if (Flags.Flag_StartMotor = 0 )then
        Flags.Flag_StartMotor = 1
        State = StartMotor  ' Start Button pressed allow start
     end if
     end if
'************************************************************
'Check if Stop Button is pressed
'************************************************************
    if Button(PORTC,13, 100, 0)= 1 then
       State = StopMotor
     end if

 '***********************************************************
    select case State
 '***********************************************************
   ''Start EC Motor
 '************************************************************
      Case StartMotor
       Flags.Flag_StartMotor = 1 'Block Start Button
       HallValue = PORTB and $38
       HallValue = HallValue >> 3
       OVDCON =  StateLowTableClk[HallValue]
       PDC1= 500
       PDC2 = PDC1
       PDC3 = PDC1
       PWMCON1 = $0777             'Enable PWM module
       State = RunContinious       'Block Start State

 '************************************************************
   'Motor is Running go in Run Mode now
 '************************************************************
      case RunContinious
      If (Flags.Flag_CalcSpeed = 1) then
           CalcSpeed()
        Flags.Flag_CalcSpeed = 0
      end if
      if (Flags.Flag_CalcDutyCycle = 1) then
         DesiredSpeed = word(CalcDutyCycle(SetSpeed,SpeedFactor))
         PDC1 = DesiredSpeed
         PDC2 = PDC1
         PDC3 = PDC2
         Flags.Flag_CalcDutyCycle = 0
      end if
  '***********************************************************
  'Errors in System Go into Error State
  '***********************************************************
      case ErrorState
     'no error stae checking implemented
      nop
 '************************************************************
   'Stop Selected - stop motor
 '************************************************************
      case StopMotor
       PDC1 = 100
       PDC2 = 100             'initialize DC register to 100
       PDC3 = 100
       PWMCON1 = $700         'Disable PWM module
       Flags.Flag_StartMotor = 0 'allow restart of Motor on Button
   end select                    ' pressed
wend
end.

'************************************************************
I hope this will help some one wanting to run BLDC motors
P.Erasmus
Saratov,Russia
--------------------------------------------------------------

rmteo
Posts: 1330
Joined: 19 Oct 2006 17:46
Location: Colorado, USA

#2 Post by rmteo » 12 Aug 2009 17:10

Thanks for doing the conversion from C to BASIC. I'm sure it will be helpful for those wanting to control BLDC's with Hall sensors.
Why pay for overpriced toys when you can have
professional grade tools for FREE!!! :D :D :D

Skyline
Posts: 267
Joined: 10 Jan 2006 09:35

#3 Post by Skyline » 13 Aug 2009 01:34

Hi,

Thanks for the code, much appreciated.

Post Reply

Return to “mikroBasic for dsPIC30/33 and PIC24 General”