zaterdag 17 november 2012

H-brug


H-brug

Inleiding


De H-brug wordt ook wel een motor-driver genoemd of een motor-ic. Dit omdat ze onlosmakelijk verbonden is met de aansturing van onze motoren. We willen het toerental van onze motoren kunnen wijzigen , net als het bepalen van de draairichting. Hiervoor zullen we dus gebruik maken van een H-brug.

Vereisten


De keuze van de H-brug , hangt af van een aantal factoren. Ten eerste de stahl current van onze motor. Dit is de piekstroom die de motor trekt als de wielen geblokkeerd worden. Onze H-brug moet deze stroompiek aan kunnen. Daarnaast moet het mogelijk zijn om via de H-brug met behulp van PWM het toerental van onze motoren te wijzigen. En dan bestaan er nog H-bruggen waar je maar 1 motor mee kan regelen en andere waar je er 2 mee kan regelen.

Keuze H-brug


De stahl current van onze motor bedraagt 1600mA, daarnaast hebben we PWM regeling nodig en beschikken we over 2 motoren waarbij we enerzijds een H-brug per motor kunnen gebruiken, maar anderzijds ook één H-brug kunnen kiezen die 2 motoren aankan.

Onze keuze viel op de L298, hij kan 2 motoren sturen waardoor we maar één H-brug nodig hebben.
Er kan ook gebruikt worden gemaakt van PWM-signalen voor de aansturing en daarnaast kan hij de stahl current van onze motoren aan want hij kan DC stromen van 4A aan en spanningen tot 46V . Hij voldoet dus ruim aan de vereisten.

Werking L298



Gelieve de Datasheet erbij te nemen , met name de pinmap van de L298.
Pin 4 en pin 9 dienen voor de spanningsvoorziening van onze H-brug. Pin 4 voor de voeding van de vermogenketen en pin 9 voor de voeding van het logische gedeelte. Bij ons hangen beide aan de batterij. Pin 6 en pin 11 zijn de signalen waarop we een PWM signaal kunnen sturen voor het toerental te regelen. Pin 1 en 15 moeten met de ground verbonden worden door een weerstand.

Pin 5 en pin 7 zijn respectievelijk input 1 en 2. Dat zijn de inputs van motor A. We kunnen hiermee de draairichting bepalen alsook een fast stop genereren afhankelijk van de signalen die we aan deze pinnen hangen. Motor B heeft ook dergelijke inputs namelijk 3 en 4 op pin 10 en pin 12. De waarheidstabel met de verschillende aanstuurmogelijkheden van deze pinnen is terug te vinden in de datasheet. Analoog met de input’s hebben beide motoren ook output’s. Output 1 en 2 voor motor A op pinnen 2 en 3, daarnaast output 3 en 4 voor motor B op pinnen 13 en 14.
Op pin 8 bevind zich de ground.

Voor verder informatie in verband met specifieke details, zoals optimale elektrische karakteristieken verwijs ik u door naar de datasheet.
Er zijn echter wel nog enkele componenten die u dient aan te sluiten aan de H-brug voor een correct werking. RsensA en RsensB zijn weerstanden die langs de ene zijde aan pin 1 en 15 hangen en de andere zijde aan de ground. Wij gebruiken hiervoor 10kOhm weerstanden. Aan pin 4 en 9 wordt ook een condensator van 100nF gehangen waarvan de andere zijde met de ground verbonden wordt.
Er worden ook Fast recovery diodes( 1A en tr≤ 200ns) geplaats rond de aansluitpunten van de motoren.  
Schema  op pagina 6 van de datasheet geeft u een voorbeeld hoe de aansluiting verloopt bij het aansturen van één enkele motor.

Bronnen


Datasheet L298

PID regeling


PID regeling


Waarom PID regeling?


We maken gebruik van een PID regeling zodat onze auto acceptabel zou reageren op de wijziging van de lijn zonder dat er instabiliteit ontstaat in het rijgedrag.

                  Met PID

               

                       Zonder PID








U ziet dat bij PID regeling de lijn constanter wordt gevolgd en geen grote wijzigingen optreden in het rijgedrag van de auto.

De formule


We starten bij de algemene formule voor een PID regeling :
<!--[if !vml]--><!--[endif]-->
Waarbij :
Kp = proportionele actie
Ki = integratie actie
Kd = differentiërende actie

Nu we deze formule weten kunnen we het programma schrijven.



Het programma


/*working variables*/
double Output;
double errSum, lastErr;
double Kp, Ki, Kd;
 
void Compute()
 
{
  
      /*Compute all the working error variables*/
      errSum += afwijking;
      double dErr = (afwijking - lastErr);

      /*Compute PID Output*/
      Output = kp * afwijking + ki * errSum + kd * dErr;

      /*Remember some variables for next time*/
      lastErr = afwijking;
}

 

Uitleg programma


De gebruikte variabelen

Output :            De waarde die na onze PID formule zal uitgekomen worden.
                         Met deze waarde gaan we de verdere berekening maken zodat we de lijn kunnen volgen.
 
afwijking :              De fout die tussen de input en de setpoint zit. Omdat onze setpoint gelijk is aan 0 is de error gelijk aan de input.
Errsum :           Is gelijk aan de error + errsum deze hebben we nodig om de integratie van onze PID te kunnen berekenen.
dErr :               Is de error – de laatste error. Deze wordt gebruikt om de defferentiatie te kunnen berekenen van onze PID.

uitleg


Voor dit programma, zullen we het programma van de sensors plaatsen. Nadat de sensoren uitgelezen zijn zal dit programma in werking treden.

De uitkomst van onze PID wordt berekend met volgende formule :

Output = kp * error + ki * errSum + kd * dErr

Output = Proportional + integral + Differential

Proportional :    Positie van de lijn – de gemeten waarde  = het verschil
                               Het verschil * kp = proportional

Integral :             Integral + het verschil = Integral
                               Integral  * ki = integral

Differential :      Verschil – het vorig verschil = Rate van het verschil
                               Rate verschil * kd = differential

Daarna zetten we het verschil vast, als het vorig verschil om de volgende waarde te kunnen berekenen.

Daarnaast zullen we ook een programma schrijven waarbij we Kp, Ki en Kd kunnen veranderen aan de hand van infrarood communicatie. Aan de hand van deze manier moeten we de microcontroller niet elke maal opnieuw programmeren om waardes aan te passen.

De Kp waarde zal ervoor zorgen dat bij een rechte lijn de lijn constant en stabiel gevolgd wordt zonder oscillatie.

De Ki waarde zal worden gebruikt om te reageren op het einde van een bocht. Deze is een heel gevoelige waarde en zal voor veel oscillatie zorgen indien het verkeerd is ingesteld.

De Kd waarde zal ervoor zorgen dat de lijn mooier gevolgd word in het begin van een bocht.

maandag 5 november 2012

Informatief: PWM sturing


PWM signaal met ATMEGA 328

Inleiding

Er zijn 6 PWM signalen beschikbaar bij de Atmega 328, dit komt voor uit volgende redenering. We beschikken over 3 inwendige timers: T0,T1,T2 ; welke elke 2 uitgangssignalen (A en B) bezitten.  Waarbij timer 0 en 2 8bit timers zijn en timer 1 een 16bit timer. Uiteraard kunnen we ook PWM signalen generen met behulp van delays of analogwrite().
Wanneer we gebruik maken van PWM signalen met behulp van timers zijn er nog 2 methodes, namelijk fast PWM en Phase correct PWM. Deze laatste methode lijkt mij het meest aangewezen voor de sturing van onze motoren. Meer informatie over de PWM phase correct vind u in de datasheet, verder in dit document vervat, op pg 128. Deze methode is echter redelijk tijdrovend en bevat enkele ingewikkelde instellingen. De methode met delays is heel eenvoudig maar lijkt voor onze toepassing niet zo gebruiksvriendelijk. Vandaar dat wij vermoedelijk zullen gebruik maken van de analogwrite methode, namelijk : efficiënt, nauwkeurig, betrouwbaar en eenvoudig.

PWM met behulp delays


 void setup ()
{
pinMode(13,OUTPUT); // output pin 13 defineren
}
void loop ()
{
digitalWrite(13,HIGH); //13 hoog zetten
delayMicroseconds(900);// vertraging van 70 % dutycycle
digitalWrite(13, LOW);//13 laag zetten
delayMicroseconds(400);// vertraging van 30 % dutycycle
}
Een frequentie van 20MHZ geeft ons een periode van 50ns vandaar de verdeling in 0,035µs en 0,015µs.


 

Phase correct PWM

Hierbij basseer ik mij op volgende tutorial PWM. Het gebruik maken van PWM met behulp van timers vergt wel wat werk ivm instellen van registers. Verdere uitleg ivm de instelling van de registers ben ik dan ook gaan zoeken in de datasheet van de Atmel Atmega 328.
Timer output
Arduino output
Chip pin
Pin name
OC0A
6
12
PD6
OC0B
5
11
PD5
OC1A
9
15
PB1
OC1B
10
16
PB2
OC2A
11
17
PB3
OC2B
3
5
PD3
 
Vereiste instellingen :
WGM: waveform generation mode : 001
COMnA/COMnB :10 voor een niet geïnverteerd PWM signaal op uitgang A en B
OCRnA/OCRnB: output control register (vergelijkingsregister) : bv 180
                 timer0 en 2 tellen van 0-255 , bij OCR register zeg je met welke waarde hij  in zijn timerregister moet vergelijken. Hierbij dus goed kijken welke timer je gebruikt (0 en 2 = 8bit en 1=16bit)
CS : clock select, hiermee selecteer je de prescaler van je timer bijvb voor 64 moet je de waarde 100 hebben
TCCRnA/TCCRnB: timer counter control registers bevatten bovenstaande instellingen.
TCCRnA bevat de COMnA/COMnB en WGM instellingen
TCCRnB bevat de CS instelling
Merk op dat den A en B hier niet verwijzen naar output A en B maar gewoon 2 registers zijn van 1 timer.  De waardes die je moet instellen verschillen voor de verschillende timers.
Een voorbeeld, WGM moet 001 zijn , voor T0 is dat WGM00, voor T1 is dat WGM 10, Voor T2 is dat WGM 20
Dit is terug te vinden in de datasheet.
in bovenstaande afkortingen moet de “n” steeds vervangen worden door 0,1,2 afhankelijk van de keuze van de timer.


 

PWM gebruik van analogwrite

Dit is volgens mij een eenvoudige, correcte en gebruiksvriendelijke manier. Vandaar dat deze methode zal gebruikt worden in ons prototype. Op een tutorial arduino pwm vind je hierover een duidelijke uitleg.
Als je weet dat een analogwrite() commando zich situeert tussen 0-255 dan kan je hierop je dutycycle berekenen. Analogwrite(127) zal een dutycycle van 50% omvatten. Hieronder een schematische weergave.
 
Ook vind je een voorbeeld programma voor het dimmen van een led in de arduinosoftware.
Via volgende weg, file>examples> analog menu, kom je tot bovenvermeld bestand.
Hieronder de code die ervoor zorgt dat we een led met pwm signaal kunnen aansturen.
int led = 5;
void setup(){
 pinMode(led, OUTPUT);
}
void loop () {
  analogWrite(led, 255);
  delay(5000);
  analogWrite(led,50);
  delay(5000);
  analogWrite(led,100);
  delay(5000);
  analogWrite(led,200);
  delay(5000);
  analogWrite(led,0);
  delay(5000);
 
}