Stap 6: programmeren
De codering voor dit is vrij eenvoudig. Er zijn slechts vier methoden te schrijven. We krijgen alle de I2C signaal onderhandelingen uit de bibliotheek van de I2C die we met de Microchip Code Configurator genereren zult.
- initWiiCam(); Alleen moest opnieuw configureren van de camera
- readWiiCam(); Vraagt van de camera voor de positie van het baken
- updatePan(); Updates van de pan indien nodig naar het midden van het baken op de X-as
- updateTilt(); De tilt bijgewerkt indien nodig naar het midden van het baken op de Y-as
Installeren van MPLABX
Dus laten we aan de slag. Eerst, download en installeer MPLABX van Microchip: http://www.microchip.com/pagehandler/en-us/family/...
Een Project maken
Zodra de installatie is voltooid, het opstarten en ga naar bestand > Nieuw Project
Hierdoor ga je via een wizard voor het configureren van ons project.
- Kies Project
- Categorieën: Microchip ingebed
- Projecten: Standalone Project
- Selecteer apparaat
- Familie: Mid-Range 8-bits MCU's (PIC12/16/MCP)
- Apparaat: PIC16F1503
- Selecteer koptekst
- -Header: Geen (of AC244051 * als u hebt en wilt gebruiken)
* Als u een debug-header gebruikt, hebt u om te bouwen van het project voor foutopsporing om te programmeren van de kop
- -Header: Geen (of AC244051 * als u hebt en wilt gebruiken)
- Selecteer gereedschap
- PICkit3 of compatibel instrument
- Selecteer Compiler
- XC8
- Selecteer Project en de map
- Naam: wat je wilt (bijv. IR_Tracking_Turret)
- Map: standaard
- Codering: ISO-8859-1
- Locatie: standaard
Oke, project gemaakt. Nu laten we genereren sommige bronbestanden.
Microchip Code Configurator (MCC)
Dit is een aardig hulpmiddel in MPLABX die u kunt selecteren en configureren van randapparatuur zoals timers, PWM generators en I2C communicatie. Nadat uw project is gemaakt ga naar hulpmiddelen > Embedded > Microchip Code Configuratior
Een scherm zal komen met de pinout van de chip en pin-toewijzingen op de juiste, en geselecteerde en beschikbaar randapparatuur aan de linkerkant. In de bovenste midden hij zal er een [Code genereren] knop. Erop te klikken zal het genereren van de code en de configuratie die u in het MCC selecteert. Want er geen bron codebestanden zijn nog, MCC vragen zal of u het wilt voor het genereren van een main.c bestand - klikt u op Ja. Zullen we de volgende randapparatuur voor onze toepassing geconfigureerd:
- TMR1 - 16-bits timer
- TMR2 - 8-bits timer
- PWM2 - PWM op pin 7
- PWM3 - PWM op pin 11
- MSSP - I2C Master, SDA op pin 9, SCL op pin 10
In de lijst op de rechter benedenhoek, zoeken en dubbelklikt u op de bovenstaande randapparaten toe te voegen het aan de lijst van geselecteerde randapparatuur op de linker bovenhoek. Zodra u ze al hebt, laten we enige ondersteuning van randapparatuur-code te genereren.
Systeem
- Systeem klok selecteren: INTOSC
- Frequentie selecteren > interne klok: 16MHz_HF
- CONFIG1 > Picssoftware Pin functie selecteren [MCLRE uit]
TMR1
- Klokbron: FOSC/4
- Prescaler: 1:8 Timer
- Periode: 100ms
- Interrupt inschakelen: controleren
- Callback functie Rate: 30 x (3s) - time-out voor opnieuw centreren het torentje
TMR2
- Prescaler: 1: 64
- Timerperiode: 4ms
- TImer start na de initialisatie: controleren
- Inschakelen van de Timer onderbreken: controleren
- Callback functie Rate: 5 x 20 (MS) - voor het besturen van de servo's, de meeste servo's zal ook werken met een periode van 12 MS.
PWM2, PWM3
- PWM inschakelen: controleren
- PWM Pin uitvoer inschakelen: controleren
- PWM polariteit: Omgekeerde (periode 4ms)
MSSP::I2C
- MASTER inschakelen I2C: gecontroleerd
- SM Bus uitvoer inschakelen: gecontroleerd
- Slew Rate Control: Hoge snelheid SDA
- Houd tijd: 100ns
- I2C klokfrequentie: 400KHz
- Slaaf adres: 7-bits
- Lees buffergrootte: 10 - afhankelijk van hoeveel bytes u terug van het apparaat verwachten u praten, in dit geval voor de eenvoudigste configuratie, de Pixart camerawill terug 10 bytes.
- Schrijf buffergrootte: 2 - zullen we naar de Pixart camera 2 bytes op een moment.
Uw eigen Code toe te voegen
Nu de meeste van de code voor het project wordt gegenereerd, maar we moeten nog sommige constanten en variabelen declareren en voeg wat extra code, waaronder vier de methoden hierboven vermeld.
Main.c
Zoek deze regel:
/* Main application */
Voeg de volgende code eronder
#define SLAVE_I2C_GENERIC_RETRY_MAX 100 I2C_MESSAGE_STATUS status = I2C_MESSAGE_PENDING; // Wii IR Camera Initialization Settings static const uint8_t wiiCameraAddress = 0x58; static const uint8_t wiiCameraReadCmd = 0x37; <p>static const uint8_t wiiCamInitData[14][2] = {{0x30, 0x01}, /* Sensitivity config Block A */ {0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x90}, // p0: MAXSIZE: Maximum blob size. Wii uses values from 0x62 to 0xc8 {0x07, 0x00}, {0x08, 0x41}, // p1: GAIN: Sensor Gain. Smaller values = higher gain /* Sensitivity config Block B */ {0x1A, 0x40}, // p2: GAINLIMIT: Sensor Gain Limit. Must be less than GAIN for camera to function. {0x1B, 0x00}, // p3: MINSIZE: Minimum blob size. Wii uses values from 3 to 5 </p><p>/* Mode config */ {0x33, 0x01}, // mode: 1=basic, 3=extended, 5=full {0x30, 0x08}};</p> uint16_t DcPan = 630; uint16_t DcTilt = 630; uint8_t writeBuffer[2], cmdBuffer[1], readBuffer[10]; uint8_t *i2cData; uint16_t b1x, b1y;
void initWiiCam(void) { for (int cnt=0;cnt<14;cnt++) { i2cData = (uint8_t *)&wiiCamInitData[cnt]; for (int i=0; i<2; i++) writeBuffer[i] = 0; writeBuffer[0] = *i2cData++; writeBuffer[1] = *i2cData++; I2C_MasterWrite(writeBuffer,2,wiiCameraAddress,&status); while (status == I2C_MESSAGE_PENDING); } }
void readWiiCam (void) { // Read Wii Camera data i2cData = (uint8_t *)&wiiCameraReadCmd; // initialize the source of the data cmdBuffer[0] = 0; cmdBuffer[0] = *i2cData++; I2C_MasterWrite(cmdBuffer,1,wiiCameraAddress,&status); // wait for the message to be sent or status has changed. while (status == I2C_MESSAGE_PENDING); //__delay_ms(3); for (int i = 0; i < 10; i++) readBuffer[i] = 0x00; i2cData = (uint8_t *)&readBuffer; I2C_MasterRead( i2cData,10,wiiCameraAddress,&status); while (status == I2C_MESSAGE_PENDING); if (readBuffer[0] != 0xFF && readBuffer[0] != 0x00) { b1x = ((readBuffer[2] & 0x30) << 4) + readBuffer[0]; b1y = ((readBuffer[2] & 0xC0) << 2) + readBuffer[1]; TMR1_CallBackReset(); } else { b1x = 0x00; b1y = 0x00; } }
void updatePan(void) { // Adjust pan and tilt servos if ((b1x == 0x00) || (b1x == 0xFF)) return; if (b1x > 522) DcPan += (b1x-522)/(20*3); if (b1x < 502) DcPan -= (502-b1x)/(20*3); if (DcPan > 875) DcPan = 875; if (DcPan < 375) DcPan = 375; PWM2DCH = DcPan >> 2; PWM2DCL = DcPan << 6; } void updateTilt(void) { if ((b1y == 0x00) || (b1y == 0xFF)) return; if (b1y > 394) DcTilt -= (b1y-394)/(20*3); if (b1y < 374) DcTilt += (374-b1y)/(20*3); if (DcTilt > 875) DcTilt = 875; if (DcTilt < 375) DcTilt = 375; PWM3DCH = DcTilt >> 2; PWM3DCL = DcTilt << 6; }
Inschakelen interrupts en voeg de volgende code toe aan de hoofdfunctie:
void main(void) { // initialize the device SYSTEM_Initialize(); // Enable the Global Interrupts // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits // Use the following macros to: INTERRUPT_GlobalInterruptEnable(); // Enable the Peripheral Interrupts INTERRUPT_PeripheralInterruptEnable(); // Disable the Global Interrupts //INTERRUPT_GlobalInterruptDisable(); // Disable the Peripheral Interrupts //INTERRUPT_PeripheralInterruptDisable(); initWiiCam(); __delay_ms(10); while (1) { readWiiCam(); updatePan(); updateTilt(); __delay_ms(10); } } /** End of File */
tmr2.c
Servo's gebruikt een puls.5 tot en met 2.5 ms een 20ms periode te bepalen de positie van hun doel. Onze configuratie geeft TImer2 een 4ms periode, die geweldig is voor het geven ons een heleboel precisie binnen die periode, maar te kort voor servo-gebruik. Dus we gebruiken een retouraanroep die door elke 5de keer Timer2 overloopt worden uitgevoerd. Wij houden PWM uitgeschakeld totdat de 5e pass, geven ons een 20ms periode met een hogere precisie pulslengte. Dit geeft ons soepeler beweging in tracking en beter antwoord op kleine bewegingen. Afdalen naar de Interrupt Service Routine (ISR) en Callback functies en bewerk ze er als volgt uitzien.
void TMR2_ISR(void) { static volatile unsigned int CountCallBack = 0;<br> // clear the TMR2 interrupt flag PIR1bits.TMR2IF = 0; TRISCbits.TRISC5=1; TRISAbits.TRISA2=1; TRISCbits.TRISC3=1; // callback function - called every 5th pass if (++CountCallBack >= TMR2_INTERRUPT_TICKER_FACTOR) { // ticker function call TMR2_CallBack(); // reset ticker counter CountCallBack = 0; } // add your TMR2 interrupt custom code } void TMR2_CallBack(void) { // Add your custom callback code here // this code executes every TMR2_INTERRUPT_TICKER_FACTOR periods of TMR2 TRISCbits.TRISC5=0; TRISAbits.TRISA2=0; TRISCbits.TRISC3=0; }
TMR1.c
Ik voegde enkel dit aan kadreren het torentje als het ziet om het even wat niet gedurende 3 seconden. We moeten de CountCallBack declareren als global. Zoek deze regel:
volatile uint16_t timer1ReloadVal;
Voeg ths lijn eronder:
volatile unsigned int CountCallBack = 0;
Nu afdalen naar de Interrupt Service Routine (ISR) en Callback functies en bewerken ze er als volgt uitzien.
VOID TMR1_ISR(void) {//static void TMR1_ISR(void) { //static volatile unsigned int CountCallBack = 0; // Clear the TMR1 interrupt flag PIR1bits.TMR1IF = 0; TMR1 += timer1ReloadVal; // callback function - called every 30th pass if (++CountCallBack >= TMR1_INTERRUPT_TICKER_FACTOR) { // ticker function call TMR1_CallBack(); // reset ticker counter CountCallBack = 0; } // Add your TMR1 interrupt custom code } void TMR1_CallBack(void) { // Add your custom callback code here const uint16_t DcTiltReset = 630; const uint16_t DcPanReset = 630; PWM3DCH = DcTiltReset >> 2; PWM3DCL = DcTiltReset << 6; PWM2DCH = DcPanReset >> 2; PWM2DCL = DcPanReset << 6; }
TMR1.h
Zoek deze regel
void TMR1_CallBack(void);
Voeg deze regel eronder
void TMR1_CallBackReset(void);
Nu alle code is op zijn plaats en w kunt bouwen en programmeren van het apparaat.
Schoon en bouwen Project, dan maken en programma apparaat. De PIC is klaar om het sluit aan op de aansluiting op de PCB.