CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

L298N

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
moha-affa



Joined: 16 May 2015
Posts: 18
Location: istanbul-turkey

View user's profile Send private message

L298N
PostPosted: Tue Jul 07, 2015 4:48 am     Reply with quote

hi ...

can L298N drive BLDC Motor ??? or i need an other driver ..

Thanks
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jul 07, 2015 5:06 am     Reply with quote

well...you could drive a 2 phase BLDC motor with one unit, a 3 phase BLDC motor with 2 BUT you really should use a proper BLDC driver chip to control a BLDC motor. The 298 is only good for 4 amps when well heatsinked, 2 chips AND heatsinks take up a lot of PCB area AND the PIC coding will be challenging especially if you're a 'newbie'.
Do the research and based on your motor's specs buy the next 'bigger' BLDC chip that will work.Be sure to follow thew datasheet for power supply, layout, and heatsinking.


Without knowing the motor you're using I can't recommend a BLDC device. Post that info and others can help.

Jay
moha-affa



Joined: 16 May 2015
Posts: 18
Location: istanbul-turkey

View user's profile Send private message

PostPosted: Tue Jul 07, 2015 5:31 am     Reply with quote

thank you ...

all i now about the motor is :

3 phase Bldc motor - 12 V

it's used it in hydrolic oil pump in car ,,,
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Jul 07, 2015 5:48 am     Reply with quote

it is the wrong chip for ANY BLDC.

You need to know much more about pump speed etc to select / create a driver for it, but bridge drivers by themselves are not the answer.

how would use ever use a DUAL bridge driver on a 3 phase motor anyway?
recall that any sensible BLDC controller must know back EMF to set switch points and the driver design must accomodate that data collection.

BLDC design is NOT trivial - BTDTGTTS
temtronic



Joined: 01 Jul 2010
Posts: 9241
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jul 07, 2015 7:27 am     Reply with quote

Microchip has several appnotes... AN587 'brushless DC motor control made easy'....uses nothing more than a PIC, some fet drivers and 6 FETs. While the code is in assembler, it ain't that complicated and could be turned into CCS C in a day or two....
Now you can use 2 of the 298s as the driver/FETs but it does require some 'fun' in cutting the code but it is possible for 'home use' NOT for 'commercial' applications.
Another possible 'driver' would be the chips for floppy drive systems.....esp the 'old' 8" floppies....

BLDC is kind of a 'generic' term so without the real data on the motor and purpose it is difficult to say 'use this device...or that'.


Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Tue Jul 07, 2015 7:52 am     Reply with quote

If you look here:
<http://www.ccsinfo.com/forum/viewtopic.php?t=54079>

What he has is a _sensored_ BLDC motor. With the sensors being part of the actual PCB, which he wants to replace. The comments made here apply to any answer. The manufacturer would not have used sensors unless they were needed, and for the load involved (oil pump), sensored would be the normal requirement. So he needs to start by working out how to build the sensor part himself. These are _part_ of the whole motor....
Then he has never answered the questions about inductance, voltage etc., which are vital to any answer.
guy



Joined: 21 Oct 2005
Posts: 297

View user's profile Send private message Visit poster's website

PostPosted: Wed Jul 08, 2015 12:20 am     Reply with quote

Hi! Disclaimer: I've never driven a BLDC motor, only steppers, but it looks similar.
https://www.youtube.com/watch?v=bCEiOnuODac
If you just want to play around with the motor (no sensors, no feedback) you will need 3 full-bridge drivers (or 2x L298N, assuming it can handle the current required). Be ready with your finger on the OFF switch in case things heat up Laughing
Maybe make a test program that starts with very low speed and increases it. This will help the motor catch speed.
Hope this helps.
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Wed Jul 08, 2015 4:34 am     Reply with quote

BLDC, and steppers don't have much in common.

With a stepper you drive each pole (or pair) in turn, and PWM, is only used to adjust the current. With BLDC, you are continuously modulating the PWM, to synthesise sinusoidal drives (like a synthesised synchronous motor), _but_ the key thing is that you adjust this to lead/lag the current position of the motor, to give the required drive. Now the problem is how you know 'where' the motor is?. One form is 'sensorless' drive, and on this you sense the position of the rotor using the BEMF on the one undriven phase (you only drive two phases at a time out of three. This works fine once the motor is spinning, but not when you start. The other way is to have separate sensors. Now the sensorless drive 'starts' by a process similar to a stepper motor, feeding a low power pattern at a low speed that the motor 'ought' to be able to handle, until it starts. Problem is that this only works if there is only a very low load at the start (so works fine for things like fans, but not for things like pumps). the sensored drive instead knows where the motor is, and can sense the position right from the start. Hence any application needing high starting torque must be sensored. So as I've already said the first thing he is going to have to crack is generating the three sensors in the right positions.

Just because it 'looks' a bit like a stepper, with 'poles' that need to be driven, don't think there is actually any real similarity, when it comes to driving them. there isn't....

As a 'quickie' for anyone wanting to play with BLDC, this is AN857, translated to run on CCS:
Code:

//Code based on AN857 for BLDC

#include <16F877.h>
#device adc=16 //Left justify the ADC
#FUSES NOWDT, HS, NOBROWNOUT, NOLVP
#use delay(clock=16MHz)

#define ManThresh (0x3F) //Change to 0xFF for manual mode - 0x3F else
#define AutoThresh (0x100-ManThresh)
int8 flags=0;
#bit DriveOnFlag=flags.0
#bit AutoRPM=flags.1
#bit FullOnFlag=flags.4
#bit Tmr0Ovf=flags.5
#bit Tmr0Sync=flags.6

int8 PhaseIndx=6,Drive,RPMIndex;
int8 ADCRPM;
int8 PWMThresh=0;
int8 ADCOffset;
int8 Vsupply;
int8 DeltaV1,DeltaV2;
int16 CCPSave,CCPT2;
int8 RampTimer;

#define AccelDelay 100
#define DecelDelay 10

#bit BEMF1Low=DeltaV1.7
#bit BEMF2Low=DeltaV2.7
#bit ADCneg=ADCOffset.7

enum {RPMSetup,RPMRead,OffsetSetup,OffsetRead,Vsetup,Vidle,Vread,BEMFSetup,BEMFIdle,BEMFRead,BEMF2Idle,BEMF2Read,Inval} STATE=RPMsetup;

#use fast_io(C)

/*
ADC channels are wired as:
AN0 = RPM I/P voltage
AN1 = Offset
AN3 = sense on OP/A BEMF etc..
*/

#define RPM (0)
#define OFFSET (1)
#define BEMF (3)

//Drive word definitions
#define OffMask (0B11010101)
#define Invalid (0B00000000)
#define Phase1  (0B00100001)
#define Phase2  (0B00100100)
#define Phase3  (0B00000110)
#define Phase4  (0B00010010)
#define Phase5  (0B00011000)
#define Phase6  (0B00001001)

//ADC switching definitions
//Each assumes the ADC is in a defined previous state, and changes it to the next
#define ADC0to1 (0B00001000)
#define ADC1to3 (0B00010000)
#define ADC3to0 (0B00011000)
#byte ADCON0=getenv("SFR:ADCON0") //0xFC2 //("SFR:ADCON0")
#byte ADRESH=getenv("SFR:ADRESH") //0xFC4 //("SFR:ADRESH")
#bit GO=ADCON0.1
#byte STAT=getenv("SFR:STATUS")
#bit CARRY=STAT.0
#bit ZERO=STAT.2
#byte TMR0=getenv("SFR:TMR0")
#byte CCP1CON=getenv("SFR:CCP1CON")
#bit SPECIAL_EVENT=CCP1CON.0

#include "T1Tableold.h" //You will need to use the code as shown and build this for your motor
//format is const int16 Timer1Table[256] = {xxx,xxx...};

#INT_GLOBAL
void timer_0_int(void) {
   Tmr0Ovf=TRUE;
   Tmr0Sync=TRUE;
   clear_interrupt(INT_TIMER0); //fastest possible int handler - relies on instructions not changing flags etc..
}

const int8 OnTable[]={Invalid,Phase6,Phase5,Phase4,Phase3,Phase2,Phase1,Invalid};
void DriveMotor(void);
void LockTest(void);

void commutate(void) {
   //Commutation triggered by CCP1IF
   if (SPECIAL_EVENT) {
      //Here special event trigger is set
      clear_interrupt(INT_CCP1);
      if (--PhaseIndx==0) PhaseIndx=6; //Handle 'bottom of table'
      Drive=OnTable[PhaseIndx];
      DriveMotor();
   }
}

void DriveOff(void) {
   set_adc_channel(RPM); //Changing to start with my current reading
   STATE=RPMSetup;
}

void main(void)
{
   int8 temp;
   output_c(0);      //Motor drivers off to start....
   set_tris_c(0);
   //setup_adc_ports(sAN0|sAN1|sAN3);
   setup_adc(ADC_CLOCK_DIV_32);

   set_adc_channel(RPM);
   setup_spi(FALSE);
   setup_timer_0(T0_DIV_2);
   enable_interrupts(INT_TIMER0);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
   setup_ccp1(CCP_COMPARE_RESET_TIMER);
   clear_interrupt(INT_TIMER0);
   enable_interrupts(GLOBAL);

   do {
      if (interrupt_active(INT_CCP1)) commutate();
      DriveOnFlag=TRUE;
      if (!FullOnFlag) {
         temp=(int8)PWMThresh+TMR0;
         if (!CARRY) DriveOnFlag=FALSE;
         DriveMotor();
      }
      LockTest();
      switch (STATE) {
      case RPMSetup:
         if (Drive==Phase1) {
            output_high(PIN_A4);
            read_adc(ADC_START_ONLY);
            set_adc_channel(OFFSET); //Offset default
            STATE++;
            Tmr0Sync=FALSE; 
            output_low(PIN_A4);
         }
         break;
      case RPMRead:
         if (adc_done()) {
            ADCRPM=read_adc(ADC_READ_ONLY);
         }
         break;
      case OffsetSetup: //Wait for Phase2 ADC Go RA3->ADC
         if (Drive==Phase2) {
            read_adc(ADC_START_ONLY); //Trigger ADC
            set_adc_channel(BEMF);
            STATE++;
         }
         break;
      case OffsetRead:
         //Wait for ADC Read ADC->ADC Offset
         if (adc_done()){
            ADCOffset=ADRESH ^ 0x80; //Generate +/- offset
            PWMThresh=ADCRPM+ADCOffset;
            if (!bit_test(ADCOffset,7)) { //Offset is +ve
               if (CARRY) PWMThresh=0xFF;
            }
            else {
               if(!CARRY) PWMThresh=0;
            }
            if (ZERO) {
               DriveOff();
               break;
            }
            FullOnFlag=FALSE;
            if (PWMThresh>0xFD) FullOnFlag=TRUE; //Fixed full on threshold
            STATE++;
         }
         break;                             
      case Vsetup:
         //wait for phase4
         if (Drive==Phase4) {
            CCP_1=Timer1table[RPMIndex]; //Table from spreadsheet
            STATE++;
         }
         break;
      case Vidle:
         //Wait for Drive ON, wait Tacq, set ADC go
         if (DriveOnFlag) {
            delay_us(8); //Tacq
            read_adc(ADC_START_ONLY);
            STATE++;
         }
         break;                 
      case Vread:
         if(adc_done()) {
            //ADC has finished
            Vsupply=ADRESH;
            STATE++;
            Tmr0Sync=FALSE;
         }
         break; 
      case BEMFSetup:
         if(Drive==Phase5) {
            if (Tmr0Sync) {
               if (bit_test(PWMThresh,7)!=0) {
                  if (DriveOnFlag==FALSE) break;
               }
               //BEMFS1
               SPECIAL_EVENT=FALSE; //Turn off event on compare
               CCPSave=CCPT2=CCP_1; //Save two copies of CCP
               CCPT2/=2; //1/2 Phase time
               CCP_1=CCPT2/2; //1/4 phase time into CCP_1
               STATE++;
            }
         }
         break;
      case BEMFIdle:
         if (interrupt_active(INT_CCP1)) {
            DriveOnFlag=TRUE;
            DriveMotor();
            Delay_us(8);
            read_adc(ADC_START_ONLY);
            CCP_1+=CCPT2; //add 1/2 phase time to give 3/4 phase time
            clear_interrupt(INT_CCP1);
            STATE++;
         }
         break;
      case BEMFRead:
         if (adc_done()) {
            DeltaV1=ADRESH-(Vsupply/2);
            STATE++;
         }
         break;
      case BEMF2Idle:
         if (interrupt_active(INT_CCP1)) {
            DriveOnFlag=TRUE;
            DriveMotor();
            delay_us(8);
            read_adc(ADC_START_ONLY);
            set_adc_channel(RPM);
            CCP_1=CCPSave; //Full time
            clear_interrupt(INT_CCP1);
            SPECIAL_EVENT=TRUE; //enable event on compare
            STATE++;
         }
         break;
      case BEMF2Read:
         if (adc_done()) {
            DeltaV2=ADRESH-(Vsupply/2);
            STATE=RPMSetup; //Changing to start with current reading
         }
         break;
      case Inval:
         STATE=RPMSetup;
         //Status=0;
         set_adc_channel(RPM);
         break;
      }   
   } while(TRUE);
}

void DriveMotor(void) {
   if (DriveOnFlag) {
      output_c(Drive | 0x80);
   }
   else {
      output_c(Drive & OffMask);
   }
}

void LockTest(void) {
   if(Tmr0Ovf==TRUE) {
      if (bit_test(PWMThresh,7)){
         //On longer than off
         if (DriveOnFlag==FALSE)
            return;
      }
      //Here drive is either on, and on>off, or drive off, and off>on - LT05
      Tmr0Ovf=FALSE;
      if (--RampTimer!=0)
         return;
      AutoRPM=TRUE;
      if (ADCRPM<=ManThresh) {
         AutoRPM=FALSE;
      }
      if (BEMF1Low) {
         //LT10
         output_low(PIN_B6);
         output_high(PIN_B7); //ahead of lock
         RampTimer=AccelDelay;
         if (AutoRPM==FALSE) {
            //Manual code
            RPMIndex=ADCRPM;
            return;
         }
         if (RPMIndex==0xFF) {
            return;
         }
         RPMIndex++;
         return;
      }
      //LT20 - else
      RampTimer=DecelDelay;
      if (!BEMF2Low) {
         output_low(pin_B6);
         output_low(PIN_B7); //behind lock
         if (AutoRPM==FALSE) {
            //Manual code again
            RPMIndex=ADCRPM;
            return;
         }
         if (RPMIndex>0) --RPMIndex;
         return;
      }
      //Showlocked
      output_high(PIN_B6);
      if(AutoRPM==FALSE) {
         //Manual code
         RPMIndex=ADCRPM;
      }
   }
}   

The table has to be built using Excel or something similar as outlined in the AN. Wiring is as for the AN.
snoop911



Joined: 24 Aug 2007
Posts: 4

View user's profile Send private message

PostPosted: Tue Sep 08, 2015 11:33 pm     Reply with quote

due to the plethora of cheap l298n boards on ebay, I was doing a similar search for l298n and bldc.

in case it helps, there's a very nice write-up of someone doing a bldc project with a an l298n:
http://www.electronics-homemade.com/BLDC.html


I hope to use a low-voltage bldc motor from a cdrom, with sensorless 6-step commutation.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group