Start Elkretssimulator Karnaughdiagram Quine McCluskey


Driva en borstlös motor

I vårt lilla robotprojekt som går framåt dock med snigelfart hör hjulen till den nedre tredjedelen av roboten. Vi slaktar en hoverboard för detta ändamål, plockar ut hjul och batterier och får allting att fungera med ny elektronik som vi kan koppla till en dator t.ex. raspberry pi.

Du måste nog veta hur en borstlös motor fungerar för att inte köra fast här. Vidare finns en snabb men konkret introduktion till hur hoverboardens borstlösa (BLDC) hjul fungerar, vilket denna elektronik specifikt handlar om.

Få en borstlös motor att snurra

Så problemet i ett nötskal här; det är alltså att läsa av 3 stycken hallsensorer i den borstlösa motorn ("hjulet") och beroende på utsignalerna från hallsensorerna, så skall vi skicka in rätt spänningar via ett slutsteg till motorns kopparlindningar. Dvs, skapa en "mjukvarukommutator". Hur svårt kan det vara?



Signalerna från hallsensorerna på hoverboardens BLDC -motor ser ut såhär.



Mjukvaru - kommutator

Det kluriga här är att matcha hallsensorernas signal för en viss bldc -motor mot rätt elektrifiering eftersom hallsensorernas signaler och drivningen de skall initiera på olika bldc -motorer kan variera.

Jag lyckades inte hitta någon dokumentering på internet för hoverboardhjulet, men jag lyckades exprimentera fram det själv ändå. Så du slipper. Såhär ser det ut. +V är alltså positiv spänning, -V negativ och 0 innebär att lindningen flyter fritt.





Är ovan vettigt? Det går absolut att begripa både elektromagneternas elektrifiering och signalerna från hallgivarna. Jag har gjort bilder över den borstlösa motorns elektromagneter och hallgivare här.

Hallsensorn och elektrifiering

Vi vill alltså läsa av motorns fas (phase nedan) med hall -sensorn och givet fasen elektrifierar vi de lindningar som fasen dikterar att vi skall göra, enligt diagrammet ovan. Vi kan göra en tabell av diagrammet ovan för medurs rotering enligt följande. Hall A,B,C döps till HA, HB, HC och motorns HIN (hög/plus) resp. LIN (låg/gnd) kan vi döpa till HIA, LIA, HIB, LIB, HIC, LIC för respektive lindning.

Medurs
HA HB HC HIA LIA HIB LIB HIC LIC
1 0 0 1 0 0 0 0 1
1 0 1 1 0 0 1 0 0
0 0 1 0 0 0 1 1 0
0 1 1 0 1 0 0 1 0
0 1 0 0 1 1 0 0 0
1 1 0 0 0 1 0 0 1


Medurs sorterat efter HAHBHC
HA HB HC HIA LIA HIB LIB HIC LIC
0 0 1 0 0 0 1 1 0
0 1 0 0 1 1 0 0 0
0 1 1 0 1 0 0 1 0
1 0 0 1 0 0 0 0 1
1 0 1 1 0 0 1 0 0
1 1 0 0 0 1 0 0 1


Jag skapar nu en lista av detta som indexeras av phase = HAHBHC som blir:
Clockwise[phase]={B11000,B110,B10010,B100001,B1001,B100100}

Moturs
HA HB HC HIA LIA HIB LIB HIC LIC
1 0 0 0 1 0 0 1 0
1 0 1 0 1 1 0 0 0
0 0 1 0 0 1 0 0 1
0 1 1 1 0 0 0 0 1
0 1 0 1 0 0 1 0 0
1 1 0 0 0 0 1 1 0


Moturs sorterat efter HAHBHC
HA HB HC HIA LIA HIB LIB HIC LIC
0 0 1 0 0 1 0 0 1
0 1 0 1 0 0 1 0 0
0 1 1 1 0 0 0 0 1
1 0 0 0 1 0 0 1 0
1 0 1 0 1 1 0 0 0
1 1 0 0 0 0 1 1 0


Jag skapar nu en lista av detta som indexeras av phase = HAHBHC som blir:
CounterClockwise[phase]={B110,B100001,B100100,B11000,B10010,B1001}

Om man tänker sig att hallgivarens signaler ansluts till PORTB's 3 minst signifikatna bitar/pinnar, så kan man sedan läsa av dessa och kalla dem t.ex. phase.

phase = PORTB & 7

Test: Läsa hallgivaren på hjulet

Jag är lite nojig kring att bara koppla upp och hoppas på tur då jag inte vill förstöra någonting. Så jag jag tar det lite steg för steg här. En viktig grej är att avläsningen av hallgivaren fungerar korrekt. Nedan följer en testuppkoppling och testprogram samt resultat.





Jag gör så att varje gång värdet på hallgivaren ändras så anropas ett interrupt (en s.k. pin-change interrupt för pinne 8,9, och 10). Det är viktigt använda antingen inbyggda funktionen INPUT_PULLUP eller fysiskt skapa en pullup annars kommer värden från hallgivaren "fladdra" och trigga en en ström av pin-change interrupt. Detta händer därför att utgången på en hallgivare är typiskt open collector och därför måste kompletteras med pull-up-motstånd. Så glöm inte detta eftersom det då blir det mysko fel.

Eftersom den inbyggda funktionen för att skriva ut binära tal inte lägger till inledande nollor - vilket jag vill ha - så har jag även skrivit en egen sådan funktion toBinary. Bara som notis.

// testprogram för hallgivare och styrsignaler

byte clockwise[8]=
{
  B000000,
  B000110,
  B011000,
  B010010,
  B100001,
  B100100,
  B001001,
  B000000
};

byte counterClockwise[8]=
{
  B000000,
  B001001,
  B100100,
  B100001,
  B010010,
  B011000,
  B000110,
  B000000
};

byte phase = 0;
byte lstPhase =0;

void setup() 
{   
  pinMode( 8, INPUT_PULLUP);  // HC Grön kabel
  pinMode( 9, INPUT_PULLUP);  // HB Blå kabel
  pinMode(10, INPUT_PULLUP);  // HA Gul kabel

  // pin change på pinne 8,9,10
  PCICR  = 1;
  PCMSK0 = 7;
  
  Serial.begin(9600); 
}

// pin change på 8,9,10 anropas nedan ISR
ISR (PCINT0_vect)
{
  phase = PINB & 7;
}

String toBinary(int n, int size)
{
    String r;
    while(n!=0) {r=(n%2==0 ?"0":"1")+r; n/=2;}
    while(r.length()<size)
      r="0"+r;
    return r;
}

void loop() 
{
  if(phase!=lstPhase)
  {
    Serial.print("Hall=(");
    Serial.print(phase);
    Serial.print(")=");
    Serial.print(toBinary(phase,3));
    Serial.print(" Medurs=");
    Serial.print(toBinary(clockwise[phase],6));
    Serial.print(" Moturs=");
    Serial.print(toBinary(counterClockwise[phase],6));
    Serial.println();
    lstPhase = phase;
  }
}

Om jag kör ovanstående program med ovan uppkoppling och jag snurrar på hoverboard -hjulet medurs får jag nu följande utdata i den seriella monitorn, vilket ju stämmer klockrent med vad man vill ha.



Snurrar jag hoverboard hjulet moturs får jag följande utdata i den seriella monitorn, vilket också är vad man vill ha.



Härligt. So far so good. Om vi vill snurra hjulet medurs så skickar vi alltså ut data från medurs -matrisen på drivkretsarna och vice versa. I teorin.

Anluta själva motorn

För anslutning till mikro-kontrollerns port D använder jag följande färger (mest för min egen koll). Det är viktigt att det blir rätt här, annars inträffar kanske tråkiga saker. Motorn är trots allt ganska stark och jag vill inte heller ha sönder någonting i onödan.

Gul (A) HIN/HIA: Gul = PD7
Gul (A) LIN/LIA: Orange = PD6
Blå (B) HIN/HIB: Blå = PD5
Blå (B) LIN/LIB: Lila = PD4
Grön (C) HIN/HIC: Grön = PD3
Grön (C) LIN/LIC: Grå = PD2

OBS. Jag fick mig ett spel och ville använda pinne 0 och 1 för att kunna programmera en promini (för en annan grej), så jag flyttade alla anslutningar 2 snäpp upp nedan (till pinne 2-7). Detta innebär också att jag gör ett bit-shift i koden (nedan) för att kompensera för denna.



Okej, så vi läser hallgivarens utdata och varje gång denna ändras så beroende på phase trycker vi helt sonika ut mönstret för elektrifieringen av motorn på t.ex. PORTD. Det behövs lite mer elektronik först.

Effektsteg

Koncept

Har gjort en skiss i simulatorn hur det skall fungera. I nedan finns inga hallgivare utan man stegar fram manuellt genom att klicka på stega. För att begripa något här behöver man förstå hur den borstlösa motorn fungerar.



Öppna i simulatorn och klicka på switchen stega fram för att stega framåt.

Kretsen ovan fungerar såhär: En 3-bitars räknare räknar upp från 0 till 5 och börjar sedan om. Notera AND -grinden vid binärt 6 (110) nollställer räknaren till position 0 igen. Räknaren pekar sedan ut ett 6-bitars värde i den egendefinierade kretsen där sambandet mellan in och ut står i tabellen ovan.

Elektronik

För att driva strömmarna till motorns lindningar behöver vi skapa de 3 halvbryggorna med transitorer som klarar hög ström. Lite alla möjliga transistorer fungerar här. Det är nog inte viktigt alls för mina behov här men de måste klara rätt så höga strömmar och effekt. Jag har bestämt mig för att Mosfet'en STP75NF75 är en bra kandidat. Den fixar 75 V 80 A och 300 Watt. Ett gäng av dessa gör jobbet (behövs 6 stycken som du ser i ovan ritning).

Datablad för STP75NF75r.

För att driva dessa transistorer sitter kretsen IR2101 som handen i handsken.



Datablad för IRS2101

På sidan 1 i ovan PDF finns sånär som vissa komponentvärden en användbar ritning. Om man tar ritningen utan komponentvärden och stoppar in lite värden och ritar om lite får jag följande. Jag har också ritat in ett "H" och ett "L". Man brukar prata om H-sidan eller H-side (som drar upp spänningen) respektivt L-side (som drar ner spänningen).



Vad gör resistorerna (organge 3) i ovan ritning? Det är s.k. gateresitorer och styr hur snabbt gate laddas på FETen, dvs hur snabb stigtiden blir för FETen. En alltför snabb stigtid kan skapa mycket störningar och introducera en del instabilitet (en fyrkantvåg är egentligen en oändlig serie med sinusvågor som kan leta sig in lite här och var, så vi vill akta oss lite för "fyrkantiga" signaler). Sen vill man såklart inte ha en alltför långsam stigtid heller, bl.a. därför att FETarna då utvecklar mycket värme.

Vad gör kondensatorn på 1 uF i dessa scheman (organge 1) ? Det är en s.k. bootstrap -konstruktion, vilket gör det möjligt använda N-kanals mosfet på H-sidan i switchen.

Bootstrap

För att fullt ut slå på en N-kanals mosfet behövs en spänning (potential) på Gate som är ca 10 volt högre än Source. Denna kondensator, som laddas via dioden (organge 2) medans L-sidan är aktiv, tillhandahåller, när H-sidan blir aktiv tillsammans med lite elektronik i ICn, denna högre spänning.



Se ovan. H-sidan är av och L-sidan aktiv och då är Vs troligen ganska nära jord och kondensatorn laddas till Vcc minus fallet över dioden.



När H-sidan slår på, så ökar spänningen (potentialen) vid Vs vilket också får spänningen vid Vb att öka med lika mycket som kondensatorn är uppladdad till, vilket blir en spänning mycket högre än Vcc (det är precis vad vi vill). Det är just därför dioden (organge 2) sitter mellan Vcc och Vb för att förhindra att den högre potentialen kommer in på Vcc. Detta gör det möjligt för spänningen vid pinne HO, för gaten, att också vara högre än Vcc, vilket är nödvändigt för att slå på H-sidan. Det som händer är alltså att vid varje omslag så laddas kondensatorn, vilket sedan används för att se till att gatespänningen är såpass hög så att H-sidan slår på. Om t.ex. spänningen UT (och därmed Vs) är 20 volt, då kommer troligtvis spänningen vid Vb vara 30 volt om Vcc är 12 v.

Spänningen ut på HO kommer ytterst från Vb (syns tydligt i "Functional Block Diagram" över IRS -kretsen). Dioden ser till att Vb är minst Vcc, men potentialen på Vb kan bli mycket högre än Vcc. Spänningen stannar då vid Vb. Låg-ESR keramisk eller tantal -kondensator bör göra jobbet. Val av diod -typ är kanske inte så kritiskt, men går det att välja någon så att urladdningen via dioden blir minimal så är det troligtvis den bästa teoretiskt (tror jag). Dock behöver inte bootstrap -kondensatorn hålla spänningen flera sekunder, utan snarare bara en bråkdel av en sekund.



Ovan nämnda konstruktion behövs 1 stycke för varje lindning, dvs det behövs totalt 3 stycken.

En konstig grej i databladet för IRS2101 är att ingången för HIN på PDIP -kapseln (vilken är den jag beställde) så ser det ut som att HIN är inverterad. Se nedan.



Lite underligt eftersom dito SOIC -kapsel inte har någon inverterad ingång. Det visar sig att detta inte stämmer. Ingången skall icke vara inverterad på PDIP kapseln heller.

En annan grej som inte finns i exempelritningen för IRS2101 -kretsen, det är att man egentligen bör ha 2 motstånd på kanske 10 KΩ ner mot GND på HIN och LIN. Jag råkade nämligen bränna en sådan här krets när jag flyttade trådarna på arduino, när spänningen var påslagen. Det är lite trist med tanke på att kretsen kostar 40 kr. Kretsen är alltså extremt känslig om strömmen är påslagen och ingångarna HIN och LIN måste då vara definierade. Ska jag vara uppriktig vet jag inte riktigt exakt varför kretsen gick sönder (tror inte det var statisk elektricitet), men 2 motstånd hade räddat den oavsett. Väl inkopplad på arduino är dock kretsen "skyddad".

Uppkoppling av drivsteget

Nedan skiss hur trådarna kopplar ihop allting. OBS i skissen nedan har jag skrivit 36 volt till effektsteget men det räcker faktiskt med 1 volt och ca 0.5 A eller lägre för att få motorn att snurra på testbänken. (36 volt är hoverboard -batteriets spänning och det motorn max klarar)



Beskåda sladdinfernot!



Transistorerna måste ha kylflänsar på sig. Ytterligare en viktig detalj är att potentialen på transistorns kylfläns varierar mellan transistorerna, vilket betyder att om de kommer emot varandra kommer det blixtra och sedan har något gått sönder. Därför måste ett silikonmellanlägg eller annan isolering (t.ex. kiselbricka med kiselfett) och plastskruvar monteras mellan transistorn och kylflänsen, så att vi riskfritt kan råka knuffa ihop kylfänsarna utan att något går sönder. Har också använd krympslang för att undvika kortslutning.



Kod

Nedan är då fungerande kod, skapade utifrån ovanstående tabeller, där vi kör ut signalern till drivkretsarna enligt vårt mönster, beroende på hallgivarens utsignal. Notera att jag flyttar utsignalerna på PORTD 2 positioner eftersom jag ville använda pinne 0 och 1 till annat. Om du sätter signalerna istället på pinne 0-5 då kan du ta bort denna bitshift.

// driva borstlös motor med hallgivare

byte clockwise[8]=
{
  B000000,
  B000110,
  B011000,
  B010010,
  B100001,
  B100100,
  B001001,
  B000000
};

byte counterClockwise[8]=
{
  B000000,
  B001001,
  B100100,
  B100001,
  B010010,
  B011000,
  B000110,
  B000000
};

byte phase = 0;
byte lstPhase =0;

void setup() 
{   
  pinMode( 0, OUTPUT); 
  pinMode( 1, OUTPUT); 
  pinMode( 2, OUTPUT); // LIC Grå = PD2  
  pinMode( 3, OUTPUT); // HIC Grön = PD3 
  pinMode( 4, OUTPUT); // LIB Lila = PD4
  pinMode( 5, OUTPUT); // HIB Blå = PD5
  pinMode( 6, OUTPUT); // LIA Orange = PD6
  pinMode( 7, OUTPUT); // HIA Gul = PD7
  
  pinMode( 8, INPUT_PULLUP);  // HC Grön kabel
  pinMode( 9, INPUT_PULLUP);  // HB Blå kabel
  pinMode(10, INPUT_PULLUP);  // HA Gul kabel

  // pin change på pinne 8,9,10
  PCICR  = 1;
  PCMSK0 = 7;

  PORTD = clockwise[PINB & 7]<<2; // startläge
  Serial.begin(9600); 
}

// pin change på 8,9,10 anropas nedan ISR
ISR (PCINT0_vect)
{
  phase = PINB & 7;
  PORTD = clockwise[phase]<<2;
}

String toBinary(int n, int size)
{
    String r;
    while(n!=0) {r=(n%2==0 ?"0":"1")+r; n/=2;}
    while(r.length()<size)
      r="0"+r;
    return r;
}

void loop() 
{
  if(phase!=lstPhase)
  {
    Serial.print("Hall=(");
    Serial.print(phase);
    Serial.print(")=");
    Serial.print(toBinary(phase,3));
    Serial.print(" Medurs=");
    Serial.print(toBinary(clockwise[phase],6));
    Serial.print(" Moturs=");
    Serial.print(toBinary(counterClockwise[phase],6));
    Serial.println();
    lstPhase = phase;
    
  }
}

Med ovan kod laddad i arduinon och alla kablar uppkopplade rätt, så börjar hjulet faktiskt att snurra riktigt fint, jämt och ljudlöst. Mycket stark motor dessutom. I logikanalysatorn ser utgångarna till motorn ut såhär.



Trevligt! Men vi är inte klara riktigt ännu.

Vi vill fartreglera vår borstlösa motor också samt göra lite allt möjligt annat också. Om detta lite längre fram i en egen tutorial.





Lite reflektioner

Ovan schema och kod fungerade faktiskt rätt så omgående vilket var väldigt uppmuntrande. Det jag upptäckte var dock att om driv-spänningen ökas mot 30-40 volt, så började lite underliga saker hända. Min första teori var att det såklart hade att göra med mitt sladd-inferno-ihopkoppling. Dvs, att konstruktionen drunknar i störningar. Jag upptäckte också när jag labbade med PWM för att styra hastigheten på motorn att "störningar" inträffade redan vid 20 volt.

Jag dumpade mitt "sladdinferno" och tillverkade ett kretskort.


Det blev en stor förbättring, men problemen fanns kvar. Så jag kommer tillverka en version 2 av kretskortet till vinter eller vår eller när det nu blir.

Jag återkommer såsmåningom med en tutorial med hastighetsreglering med PWM.

På återseende!

PS. När kretskortet fungerar så kommer det finnas ett gäng för de som är intresserade. Det är ju lika dyrt låta tillverka 1 som 200 ...