PIC RC Motor Controller (och exempel lego roboten) (2 / 6 steg)

Steg 2: programvara



Detta steg kommer att gå igenom varje del av programvaran och förklara vad den gör. Om du har något intresse av ändra programvaran och bara vill bygga sak, du kan gå på till nästa steg. Hex filen som kommer att göra projektet fungerar som avsett.

Grundläggande configureation av chip periferials
#pragma config OSC = INTIO2, WDT = OFF, lägsta värdets princip = OFF
#include < p18f1320.h >

Detta anger oscillatorn till inre och läser in inställningarna för 18F1320, om du vill använda en annan bild som detta är en av de viktigaste saker du kommer att behöva ändra

setup stift för PWM input
#define ReceiverPin PORTBbits.RB3
#define ReceiverTris TRISBbits.TRISB3

Detta är bara att ge ett namn till stift för att ta emot signalen så det är tydligare att hänvisa till.

PWM fånga variabler
unsigned int PWM1RiseTime = 0; timer-värde vid stigande kanten fånga
unsigned int PWM1FallTime = 0; timer-värde på fallande kant capture
unsigned int PWM1Width = 0; beräknade bredd

unsigned int CH1_width = 0;
unsigned int CH2_width = 0;
unsigned int CH3_width = 0;
unsigned int PWMGap = 0; beräknade klyftan mellan pulser

char PWM1Edge = 1; kant för närvarande som övervakas 1 = stigande, 0 = faller

knappen variabler
unsigned char button_1_debounce_wait = 0;

Eftersom PWM signalen från mottagaren kommunicerar med deklareras sändande pulser av varierande bredd variabler för att hålla dessa bredder när de beräknas.

unsigned char calibration_mode = 0;
#define mode_operate 0
#define mode_CH1_high 1
#define mode_CH1_med 2
#define mode_CH1_low 3
#define mode_CH2_high 4
#define mode_CH2_med 5
#define mode_CH2_low 6

unsigned int limit_CH1_high = 2381;
unsigned int limit_CH1_med = 3307;
unsigned int limit_CH1_low = 4286;

unsigned int limit_CH2_high = 2022;
unsigned int limit_CH2_med = 2946;
unsigned int limit_CH2_low = 3983;
unsigned int CH_temp = 0;

När kalibrering läge har på systemet kommer att återställa dessa "gränser" för att passa signalen. Dessa standardvärden, hur kalibreringen fungerar kommer att förklaras senare.

motorisk kontroll variabler
#define Motor_PWM_Rez 16 //number om olika hastigheter möjligt framåt och bakåt
#define center_buffer 20 //this är del av intervallet innan rörelsen startar

Detta är konstanter som du kan justera om du använder olika delar. Center bufferten är verkligen döda zonen i mitten där registeransvarige inte kommer att göra den motor gör något. Rezolution är hur många olika hastigheter systemet kommer att dela upp det utbud av kontroll i.

unsigned char Motor_Phase = 0; //as det cykler detta kommer då motorerna

unsigned int CH1_range = 2000.
unsigned char Motor_A_Speed = 0; Detta är hastigheten på motor A, på % 100 det kommer att motsvara rezolution
unsigned char CH1_forward_increment = 10; //the bredd i intervall för varje hastighet utgång
unsigned char CH1_reverse_increment = 10;

unsigned int CH2_range = 2000.
unsigned char Motor_B_Speed = 0; Detta är hastigheten på motor A, på % 100 det kommer att motsvara rezolution
unsigned char CH2_forward_increment = 10; //the bredd i intervall för varje hastighet utgång
unsigned char CH2_reverse_increment = 10;

TypeDef struct
{
osignerade motor_A_Direction: 1;
osignerade motor_B_Direction: 1;
osignerade button_1_last_state: 1;
} BITAR;

unsigned char motor_A_inverted = 1; //this relaterade till kalibrering
unsigned char motor_B_inverted = 1;
unsigned char motor_calibration_needed = 1;

flyktiga bitar bitar;

timing variabler
unsigned char slow_count = 0; Detta används för att skapa den skalförändrade timern för långsammare händelser

Variabeln ovan att bara vara en räknare så att ett underavsnitt av timer avbrottet kan gå bort endast var en av många timer-signaler.

Ställ in avbrott
void low_ISR (void); //prototype
#pragma kod low_vector = 0x08 //0X08 är låg 0X18 är hög
void low_interrupt (void) {
_asm gå till low_ISR _endasm
}
#pragma kod
#pragma avbrott low_ISR

Denna del är inte avbrottet i sig utan det Sets up för avbrott förekomma. Avbrottet är bara en händelse som gör något som utlöses så att programmet behöver inte vara en stor ögla.

void main(void)
{
OSCCON = 0X72; 8MHz klocka
tag (!. OSCCONbits.IOFS); Vänta på OSC att bli stabil

Konfigurera timer1
PIR1bits.TMR1IF = 0; rensar flaggan timer 1 avbryta
T1CONbits.TMR1ON = 1; slå på timern
T1CONbits.T1CKPS1 = 0; ställa in prescaler
T1CONbits.T1CKPS0 = 0; ställa in prescaler

setup timer2
PIR1bits.TMR2IF = 0; rensar flaggan timer 2 avbryta
PIE1bits.TMR2IE = 1; Aktivera avbrottet
PR2 = 199;
T2CON = 0b00000100; (-) alltid 0 (-) postscale (-) på/av (-) prescale

Konfigurera CCP1
CCP1CON = 0b0000101; Konfigurera CCP1 för fångst, stigande kanten
INTCONbits.PEIE=1; Aktivera perifera avbryter
PIE1bits.CCP1IE=1; aktiverade CCP1 avbrott
INTCONbits.GIE=1; Aktivera branchning om du vill avbryta
ReceiverTris = 1; Ställ in RB3 för indata så att fånga kan arbeta.
TRISBbits.TRISB2 = 1; som rb2 för så det kan användas för att skilja kanaler

Fånga modul gör alla tunga arbete här. Framför det har initierats för att vänta på signalen att stiga, senare detta kommer att ändras dynamiskt för att fånga pulse bredd.

Konfigurera portarna
ADCON1 = 0XFF; alla digitala
INTCON2bits.RBPU = 0; Port b svag pullups på

dessa kommer att vara motor utgångar
TRISAbits.TRISA0 = 0;
#define Motor_Pin_A1 LATAbits.LATA0
TRISAbits.TRISA1 = 0;
#define Motor_Pin_A2 LATAbits.LATA1
TRISAbits.TRISA2 = 0;
#define Motor_Pin_B1 LATAbits.LATA2
TRISAbits.TRISA3 = 0;
#define Motor_Pin_B2 LATAbits.LATA3

Dessa kommandon in stiften behövs för att kontrollera motorerna som utgångar. Sedan namnges motor stiften för enkel åtkomst.

dessa kommer att indikatorn utgångar
TRISAbits.TRISA6 = 0;
TRISAbits.TRISA7 = 0;

Detta kommer att vara servo signalingång
TRISBbits.TRISB0 = 1;

först kalibrera RC spänner
motor_calibration_needed = 1;

While(1)
{
}
}

Detta medan loopar håller programmet från slut. Inte luras av det faktum att det är tomt. Avbrott kommer att utlösa händelser och timern är fortfarande igång.

Nedan är början på timer avbrottet. Den slocknar regelbundet vid den högsta hastighet som någon funktion kräver, för snabba åtgärder som beslutar om det är dags att aktivera eller inaktivera motorn, då är indelad med räknare att använda de funktioner som inte kräver så hög hastighet, som övervakning indata och beslutar om hastigheten behöver förändras.

void low_ISR(void)
{

Timer 2 flaggan (för närvarande att avbryta vid 10Khz)
IF(PIR1bits.TMR2IF == 1)
{
PIR1bits.TMR2IF = 0; rensar flaggan timer 1 avbryta

Så att inte slösa tid att göra saker snabbare än nödvändigt (ett bra sätt att se på många typer av arbete) använder delen nedan variabeln "slow_count" att bara köra varje 100 gånger den yttre loopen körs.

Withen funktionen körs på 100 Hz ***
slow_count ++;
IF(slow_count > 100)
{
slow_count = 1; //reset räkna till nästa gång

Hantera kalibrering knappen
IF(button_1_debounce_wait > 0) {button_1_debounce_wait--;}
IF(PORTBbits.RB0 == 0) {
om (Bits.button_1_last_state == 0 & & button_1_debounce_wait == 0) //button bara tryckte
{
button_1_debounce_wait = 10; //set Dämpningstid greve
calibration_mode ++;
IF(calibration_mode > 6) {calibration_mode = 0;}
}
BITS.button_1_last_state = 1;
}
annat
{
BITS.button_1_last_state = 0;
}
slutet av kalibrering knappen

Nedan tillämpas kalibreringen faktiskt. Detta görs i normal driftläge så lamporna är avstängda båda. Programmet kontrollerar om mätområde är bakåt, hög är lägre än låg och vice versa, och så sätter en flagga så att riktningarna av motorerna kommer att agera därefter.

Handtag Led indikatorer läge
IF(calibration_mode == mode_operate)
{
LATAbits.LATA6 = 0;
LATAbits.LATA7 = 0;

IF(motor_calibration_needed == 1)
{
motor_calibration_needed = 0; Rensa flagga

räkna om kalibrering variabler för CH1
IF(limit_CH1_low < limit_CH1_high) //speed ökar antal ökar
{
motor_A_inverted = 0;
}
annat / / hastighet minskar lika antal ökar
{
byta dem så höga är det större värdet
CH_temp = limit_CH1_low;
limit_CH1_low = limit_CH1_high;
limit_CH1_high = CH_temp;

motor_A_inverted = 1;
}

CH1_range = limit_CH1_high-limit_CH1_low;
CH1_forward_increment = (limit_CH1_high-limit_CH1_med-((limit_CH1_high-limit_CH1_med)/center_buffer)) / Motor_PWM_Rez;
CH1_reverse_increment = (limit_CH1_med-limit_CH1_low-((limit_CH1_med-limit_CH1_low)/center_buffer)) / Motor_PWM_Rez;
}

räkna om kalibrering variabler för CH2
IF(limit_CH2_low < limit_CH2_high) //speed ökar antal ökar
{
motor_B_inverted = 0;
}
annat / / hastighet minskar lika antal ökar
{
byta dem så höga är det större värdet
CH_temp = limit_CH2_low;
limit_CH2_low = limit_CH2_high;
limit_CH2_high = CH_temp;

motor_B_inverted = 1;
}

CH2_range = limit_CH2_high-limit_CH2_low;
CH2_forward_increment = (limit_CH2_high-limit_CH2_med-((limit_CH2_high-limit_CH2_med)/center_buffer)) / Motor_PWM_Rez;
CH2_reverse_increment = (limit_CH2_med-limit_CH2_low-((limit_CH2_med-limit_CH2_low)/center_buffer)) / Motor_PWM_Rez;

}
slutet av indikatorer ledde läge

Under kalibreringen hanteras. Varje gång knappen trycks kalibrering lägesändringar, som anger att en ny gräns anges. Mönstret är CH1 full framåt mitten vila, full bakåt, då samma tre positioner igen på kanal två. De ljusa indikatorerna Visa för inte i kalibrering läge, en på för framåt, den andra för omvänd och både för mitt vilande punkt. Det är inte en robust gränssnitt men det får jobbet gjort.

Kalibrering
IF(calibration_mode == mode_CH1_high)
{

Allt detta LATA saker är bara lampor slås på att ange läge för användaren. Som ni kan se det sätta inte faktiskt gränser när du trycker på knappen. Det sätter dem bara på vilken plats de är i det läget, så när du trycker på knappen igen och att läget slutar, som håller kalibreringspunkten.

LATAbits.LATA6 = 0;
LATAbits.LATA7 = 1;

limit_CH1_high = CH1_width;

}
IF(calibration_mode == mode_CH1_med)
{
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 1;

limit_CH1_med = CH1_width;
}
IF(calibration_mode == mode_CH1_low)
{
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 0;

limit_CH1_low = CH1_width;
}
IF(calibration_mode == mode_CH2_high)
{
LATAbits.LATA6 = 0;
LATAbits.LATA7 = 1;

limit_CH2_high = CH2_width;
}
IF(calibration_mode == mode_CH2_med)
{
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 1;

limit_CH2_med = CH2_width;
}
IF(calibration_mode == mode_CH2_low)
{
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 0;

limit_CH2_low = CH2_width;

motor_calibration_needed = 1;
}

Nu behöver de motoriska hastigheterna beräknas. Ekvationen blir bredden på pulsen för det motoriskt, avgör om det är över mittpunkten eller inte att bestämma riktning, då finner den har varierar med motorstyrning resolutionen inom den totala utbud av möjliga bredder.

beräkna varvtal A
Motor_A_Speed = 0;
IF(CH1_width > limit_CH1_med+((limit_CH1_high-limit_CH1_med)/center_buffer)) //upper utbud
{
Motor_A_Speed = (CH1_width-limit_CH1_med-((limit_CH1_high-limit_CH1_med)/center_buffer)) / CH1_forward_increment;
BITS.motor_A_Direction = motor_A_inverted;
}
IF(CH1_width < limit_CH1_med-((limit_CH1_med-limit_CH1_low)/center_buffer)) //lower utbud
{
Motor_A_Speed = (limit_CH1_med-CH1_width-((limit_CH1_med-limit_CH1_low)/center_buffer)) / CH1_reverse_increment;
BITS.motor_A_Direction =! motor_A_inverted;
}

beräkna varvtal B
Motor_B_Speed = 0;
IF(CH2_width > limit_CH2_med+((limit_CH2_high-limit_CH2_med)/center_buffer)) //upper utbud
{
Motor_B_Speed = (CH2_width-limit_CH2_med-((limit_CH2_high-limit_CH2_med)/center_buffer)) / CH2_forward_increment;
BITS.motor_B_Direction = motor_B_inverted;
}
IF(CH2_width < limit_CH2_med-((limit_CH2_med-limit_CH2_low)/center_buffer)) //lower utbud
{
Motor_B_Speed = (limit_CH2_med-CH2_width-((limit_CH2_med-limit_CH2_low)/center_buffer)) / CH2_reverse_increment;
BITS.motor_B_Direction =! motor_B_inverted;
}
slutet av beräkning av varvtal

} //end av 100hz avsnitt

Här den om uttalande och counter som orsakar ovan för att bara köra på 100Hz har avslutats och vi är på full timer avbrott frekvens. Delen nedan handtag alstra den motorisk kontroll från den hastighet som beräknats ovan

Contol pulser till motor
Motor_Phase ++;
IF(Motor_Phase > Motor_PWM_Rez) {Motor_Phase = 1;}

Motoriska A
om (Motor_A_Speed > = Motor_Phase & & Motor_A_Speed < 20) {
IF(BITS.motor_A_Direction == 0) {
Motor_Pin_A1 = 1;
Motor_Pin_A2 = 0;
}
IF(BITS.motor_A_Direction == 1) {
Motor_Pin_A1 = 0;
Motor_Pin_A2 = 1;
}
}
annat {
Motor_Pin_A1 = 0;
Motor_Pin_A2 = 0;
}

Motor B
om (Motor_B_Speed > = Motor_Phase & & Motor_B_Speed < 20) {
IF(BITS.motor_B_Direction == 0) {
Motor_Pin_B1 = 1;
Motor_Pin_B2 = 0;
}
IF(BITS.motor_B_Direction == 1) {
Motor_Pin_B1 = 0;
Motor_Pin_B2 = 1;
}
}
annat {
Motor_Pin_B1 = 0;
Motor_Pin_B2 = 0;
}

} //end timer avbrottsmetoden

Nedan är början av KKP avbrottet. Detta är den del som hanterar mäta puls bredd. Det var tidigare bestämt att utlösas av en stigande kant. När den upptäcker stigande kanten kommer den registrera tiden med CCPR1 då det kommer att växla för att titta på för att falla och ändra variabeln PWM1Edge till match. När den upptäcker faller det växlar tillbaka och registrerar tiden.

CCP-avbrott
IF(PIR1bits.CCP1IF == 1)
{
PIR1bits.CCP1IF = 0; Avmarkera flaggan
IF(PWM1Edge == 1) //if upptäcka stigande
{
CCP1CON = 0b0000100; //switch att upptäcka fallande kant
PWM1Edge = 0; //switch att indikera fallande kant är nästa
PWMGap = CCPR1 - PWM1FallTime; beräkna skillnaden mellan puls startar
PWM1RiseTime = CCPR1; //save låg timer-värde för stigtiden

IF(PWMGap < 10000) {CH2_width = PWMGap;}

}
annat //if upptäcka faller
{
CCP1CON = 0b0000101; //switch att upptäcka stigande kanten
PWM1Edge = 1; //switch att ange stigande kanten är nästa
PWM1Width = CCPR1 - PWM1RiseTime; (pwm upphov är den tid som pwm uppgång inträffade)
PWM1FallTime = CCPR1; //save låg timer-värde för hösten gången

Du måste verkligen förstå logiken bakom denna del om du vill ändra koden för att arbeta med andra mottagare. Traxxas mottagaren använde jag sätter alla pulserna rygg mot rygg. Detta gjorde det så att jag inte kunde läsa igenom en pin eftersom hela uppsättningen av pulser var en lång puls när de kombineras. Så jag utformat programmet så chipet är bara ansluten till varje andra utdata, utgångar i detta fall servo 1 och 3. Så finns det en lucka. Kort klyftan (en mindre än 10000 som upptäckts av if uttalande nedan) är den mellanliggande och är längden av den mellersta pulsen, puls nummer 2. Den första pulsen efter långa klyftan är puls nummer 1 och en efter kort klyftan är puls nummer 3.

IF(PWMGap > 10000) {CH1_width = PWM1Width;}
IF(PWMGap < 10000) {CH3_width = PWM1Width;}
}

}
}

Du får gärna ställa frågor. Den kommer att hjälpa mig göra det tydligare så jag uppskattar verkligen dem.

Som jag nämnde i det senaste notera kretsar denna plan kring pulserna inträffar rygg mot rygg. Vissa mottagare space dem. Om i så fall behöver du inte göra detta trick alls. I stället skulle du bara veta att efter långa klyftan var puls en, sedan efter varje extra kort öppning du tittade på puls 2, 3, 4 och så vidare. Du skulle bara göra en variabel att hålla reda på hur många pulser du hade fångats sedan sista klyftan och återställa det när du hade den långa en, sedan använda den för att avgöra vilken kanal du tillskrivas en infångad pulse bredd.

Se Steg
Relaterade Ämnen

Elektrisk cykel (ebike) ombyggnadssats församling - hub motor, controller och batteri pack installation

Detta instructable är avsedd att hjälpa dig att spara tid och besvär om du väljer att konvertera din egen cykel till en elektrisk cykel med hjälp av en elektrisk cykel konverteringssats.2010-11-18 uppdateringar:Jag nu dubbel kolla alla leverantörer f...

Undvika hinder robot med L298N dubbla H-Bridge Motor Controller och ultrasonic sensor

Hej stötarna!jag meddelanden här några bilder av robot:den hårdvara som krävs:Arduino bakbord.bakbord.Ultrasonic sensor.2 DC motorersladdar.L298N dubbla h bro motor controller.aluminium chassi.arduino koden:http://sh.St/PQEQTLycka till!!....

24V Motor Controller för $24, RC & Arduino

Som många människor, har jag velat använda basen på en elrullstol för fjärrkontrollen projekt. Dock rätt motor styrenheter är dyra, och jag tänkte att det måste finnas en billigare lösning. Jag ursprungligen köpte borstad råden (elektronisk Hastighet...

Arduino Lego EV3 motor controller spara $45

Genom att göra en diy lego ev3 motor controllerSteg 1: Intro Så jag har ett kit som heter lego mindstorms EV3 är det en häpnadsväckande $349 robotics kit som verkligen är enkel att bygga som lego men har verkligen awesome funktioner den kit funktione...

Göra din egen Lego Motor fallet och Shaft Adapter

i detta instructable jag kommer att täcka motor hölje och axel adaptern. Kretsen för makt och kontroll jag lämnar för en annan instructable men jag kommer att besvara de flesta frågor i kommentarerna.I den sista sidan kommer jag att diskutera några a...

Enkla och billiga 6 ben Spider Lego roboten

Ledsen för typ av rush för det här dokumentet.Detta är en enkel 6 ben, 12 mini servo spider och göra används av Lego platta, kan du lägga till fler lego på din slutliga utformningen. Kostnaden är bara 12 mini servon + 3d tryckta Lego mount + din Lego...

Hund Bot: Lego roboten Rover med webbkamera

Här är hur man gör en Lego-robot kan du styra från valfri skärm över wifi. Det har också en webbkamera så att du kan se där din pågående och LED lights för ögonen! Detta är ett stort projekt att göra med dina barn som de kan göra logotypen byggnaden...

Znap Lego roboten

Denna handledning fungerar som en guide till att bygga och programmera små, hårda och autonoma monster roboten Znap. Genom projektet lär du inte bara lego konstruktion men EV3 programmering också. Se till att noggrant läsa varje steg, utnyttja alla h...

PWM solar controller och tracker

PWM solar controller och trackerSteg 1: IntroduktionPV-program kunde grupperas enligt schemat för interaktion med verktyg rutnät: rutnät ansluten, fristående och hybrid. PV-system består av en PV generator (cell modul och array), energi lagringsenhet...

Hemgjord 100 HP Motor Controller för en elbil

detta instructable förklarar hur du bygger din egen 100 Hästkrafter (topp) motor controller för användning i en elektrisk bil eller motorcykel konvertering. Det kan ta någon spänning upp till 144v toppströmmen är 500 ampere. Kostnaden för komponenter...

200kW AC Motor Controller för elektriska bil

Elbilar är framtiden, och börjar ta fart idag. Men är de fortfarande ganska dyrt. En 3 fas AC-motor är absolut standard för företag när de gör en elbil. Tesla Roadster, Nissan Leaf, etc... Alla de stora pojkarna använder AC. Den har ett antal fördela...

12-24v DC motor controller med en EG1 SPLat PLC

Det finns inte många enkla programmerbara DC motor controller instruktioner ute men nu vill jag ge dig steg för steg instruktioner om hur man gör en som kan utvidgas för användning på robotar till en 500W elektriska gå vagn!(Obs detta instructable vi...

Kontrollera Actobotics dubbla Motor Controller

Actobotics dubbla Motor Controller (DMC) kan styra 1 eller 2 motorer på 4,8 – 16 volt och leverera 20 ampere per motor kontinuerligt och upp till 30 ampere per motor ögonblickligt (topp). Det finns ett antal olika sätt du kan styra DMC, till exempel:...

Solid-State Halloween controller och hur man bygger en Haunted House

detta var ursprungligen en artikel i gör 03 där min awesome redaktör Paul Spinrad faktiskt gjorde en kopia av min controller och gjorde ett mycket bättre jobb som dokumenterar det än jag skulle. För styrkort, kolla om du behöver mer förklaring än "få...

Hjälp av WASP Motor Controller (ESC)

I detta Instructable kommer vi att lära att styra en geting motor controller med en Arduino.WASP motor controller är en elektronisk Varvtalsregulator (ESC), ta en RC signalingång från en Arduino och öka det till en hög spänning. GETINGEN tar en power...

QuickStart - en transistor DC motor controller

detta är en PWM (Pulse bredd moduleras) motor controller.En enda liten transistor används för att köra en liten likströmsmotor.Medan kretsen är mycket rakt fram (vissa säger tråkiga?) har enganska cool trick i programvaran - Pulse bredd modulerade (P...

Arduino moduler - L298N dubbla H-Bridge Motor Controller

Snabb och enkel start guide för att använda och utforska en L298N Dual H-Bridge Motor Controller module med en Arduino.Modellen i exemplet jag använder är från Ebay.Material som behövs:L298N dubbla H-Bridge Motor Controller module (olika modeller fun...

Uppgradering av Ember's Motor styrelsen och frontpanelen

Förutom mikroprocessor som kör det huvudsakliga systemet (den som du kan uppgradera genom att klicka på uppgradera firmware), det kallas två mindre marker AVRs eller ATmegas som styr motorer och frontpanelen visas. För tidig bygger på den glödande ko...

Attiny85 som steg/Dir Stepper Motor Controller

Någonstans i Grekland gjorde någon något aldrig gjort förut...Sett dessa saker innan?Sak: 1Sak: 2Sak: 3Åh, har du! Du köpte en av dem säger du? Åh... Oroa dig inte, jag gjorde också.De gjorde jobbet, ja. Men vi betalade för dem mycket. Verkligen myck...