Forum: Mikrocontroller und Digitale Elektronik RC Servo/Fahrtregler PWM für PIC18f4550


von xxx x. (Firma: xxx) (shorty1990)


Lesenswert?

Hallo


Ich brauche dringend eure Hilfe.

Ich arbeite momentan an einem Projekt.
Ziel dieses Projektes ist es eine Sende/Empfangseinrichtung für ein RC 
car zu bauen.mit dieser soll 1 Servo und 1 fahrtregler per PWM gesteuert 
werden. Mithilfe der von Microchip Solutions mitgelieferten 
Mikrocontroller Firmware habe ich es bereits geschafft code vom PC zum 
uc  über den usb serial emulator zu senden.

Leider habe ich zu spät gemerkt das der PIC18 keine Hardware PWM mit 
20ms Periodenlänge unterstützt.

Nach ca 3h googlen mit einem Freund haben wir versucht anhand dieser 
Anleitung http://www.ermicro.com/blog/?p=771 eine Interruptgesteuerte 
PWM zu Programmieren.

Leider ist uns das nicht gelungen.

Könnt ihr mir sagen was wir falsch gemacht haben?


Hier der code:


[c]void Interrupt_PWM (void);

// Interupts
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
void _high_ISR (void)
{
    _asm goto Interrupt_PWM _endasm
}

#pragma code _LOW_INTERRUPT_VECTOR = 0x000818
void _low_ISR (void)
{
    _asm goto Interrupt_PWM _endasm
}
#pragma code



/** I N C L U D E S 
**********************************************************/
#include <p18cxxx.h>
#include <usart.h>
#include <delays.h>
#include "system\typedefs.h"
#include "system\usb\usb.h"
#include "io_cfg.h"             // I/O pin mapping
#include "user\user.h"
/** V A R I A B L E S 
********************************************************/
#pragma udata
char input_buffer[64];
char output_buffer[64];
unsigned int counter;

int NurEinmal = 1;
int Puls_Max = 0;
int Puls_Top = 0;
int Top_Wert = 0;
const int Max_Wert = 200;
/** P R I V A T E  P R O T O T Y P E S 
***************************************/
void BlinkUSBStatus(void);
void User_Process(void);
void SendADC(void);
void ReadPOT(void);

#pragma code
void UserInit(void)
{
    mInitAllLEDs();
    mInitPOT();
    ADCON2bits.ADFM = 1;   // ADC result right justified
}//end UserInit

void ReadPOT(void)
{
    ADCON0bits.GO = 1;              // Start AD conversion
    while(ADCON0bits.NOT_DONE);     // Wait for conversion
    return;
}//end ReadPOT

void SendADC(void)
{
    ReadPOT();
  input_buffer[0] = ADRESH;
  input_buffer[1] = ADRESL;

    if(mUSBUSARTIsTxTrfReady()){
    mUSBUSARTTxRam((byte*)input_buffer,2);
  }
}

void Interrupt_PWM (void)
{
  Puls_Max++;
  Puls_Top++;

  if (Puls_Max >= Max_Wert)
  {
    Puls_Max = 0;
    Puls_Top = 0;

    PORTCbits.RC2 = 0;
    PORTBbits.RB7 = 1;
  }

  if (Puls_Top == Top_Wert)
  {
    PORTCbits.RC2 = 1;
  }

  if (Puls_Max == 100)
  {
    PORTBbits.RB7 = 0;
  }

  INTCONbits.TMR0IF = 0;
}



//pwm
/*void init_pwm(void){
TRISCbits.TRISC2 = 0;
PORTCbits.RC2 = 1;
PR2 = 0b00001110;
T2CON = 0b00000111;

CCP1CON = 0b00011100;


}




void User_Process(void)
{
  // FOSC/4  PS  TMR0

  if (NurEinmal = 1)
  {
    TRISB = 0x00;

    T0CON = 0b10001000;
    TMR0H = 0b00000100;
    TMR0L = 0b11000100;

    INTCONbits.TMR0IF = 0;
    INTCONbits.TMR0IE = 1;
    INTCONbits.GIE = 1;

    Puls_Max = 0;
    Puls_Top = 0;
    Top_Wert = Max_Wert;

    NurEinmal = 0;
  }[c/]

von EGS_TI (Gast)


Lesenswert?

Boah Leute, das wurde im Microchip-Forum rauf und runter diskutiert, wie 
man eine 20 ms Periode erreichen kann...

von EGS_TI (Gast)


Lesenswert?

Sodele, hier hab ichs mal rausgesucht:
http://www.microchip.com/forums/tm.aspx?m=627804&high=servo

von xxx x. (Firma: xxx) (shorty1990)


Lesenswert?

Danke
Da werde ich mich jetzt erstmal reinlesen.

Und sorry bin erst seid heute hier im Forum angemeldet.Ich hatte eig die 
sufu verwendet,aber bin auf nichts brauchbares gestoßen.
Liegt warscheinlich daran weil das alles noch recht neu ist für mich^^.

von EGS_TI (Gast)


Lesenswert?

Das hat ja nichts mit diesem Forum zu tun. ;)

Aber da haste erstmal was zu lesen.
Ich empfehle dir die "steering method", wirst beim Lesen dann schon 
sehen was das ist.

Bevor du das dann in den PC reinhackst, empfehle ich dir zusätzlich noch 
einen Programmablaufplan vor der Programmierung zu erstellen.

Viel Spaß!

von xxx x. (Firma: xxx) (shorty1990)


Angehängte Dateien:

Lesenswert?

So,
ich hab mir das jetzt alles mal durchgelesen . Aber irgendwie werde ich 
jetzt noch nicht wirklich schlau daraus.

Das Problem ist das ich diese pwm dringend brauche da das Projekt ein 
Schulprojekt ist und ich schon ganz schön im Zeit Stress bin.


Deswegen habe ich nochmal ein bisschen was gebastelt. Aber leider ohne 
erfolg.

Für das Projekt ist es egal ob der Code optimiert ist oder wie fein die 
pwm ist. Die pwm muss einfach für 10 min(die Präsentation) laufen.
Später wenn ich die Zeit dafür habe bin ich der letzte der nein sagt
und will die pwm auch "richtig" machen.

Könntest du bitte mal über den hier Angehängten code schauen und mich 
berichtigen bzw sagen ob die pwm überhaupt auf diese weise funktionieren 
kann?

von Martin S. (drunkenmunky)


Lesenswert?

Nur weil du eine Funktion Interrupt_PWM nennst, heißt das nicht dass sie 
durch ein Interrupt aufgerufen wird!

Weißt du eigentlich was ein Interrupt ist?

Bei den PIC18 gibt es nur zwei verschiedene Interruptadressen für die 
zwei verschiedenen Prioritäten von Interrupts. In deinem Programm sind 
dafür schon die Interrupt-Service-Routinen dafür angelegt. Sie heißen 
_high_ISR und _low_ISR.

Jetzt musst halt schauen, wie es eingestellt ist, ob Timer0 die hohe 
oder die niedrige Priorität bei einem Interrupt auslöst.

von Martin S. (drunkenmunky)


Lesenswert?

Wenn der Controller eh nichts anderes macht ausser den Servo anzusteuern 
und du vom Programmieren auch keine Erfahrung hast, dann mach es doch 
so, dass du den Ausgang setzt und über entsprechende Zeitfunktionen 
deine gewünschten 1-2ms wartest und dann den Pin wieder zurücksetzt. 
Danach wartest du 18ms.

von xxx x. (Firma: xxx) (shorty1990)


Lesenswert?

Ja das stimt leider nicht ganz ich muss wie in meinem 1. Post gesagt 1 
Servo und 1 Fahrtregler ansteuern die Stellung der "servos" bestimme ich 
über die Softwarekomponente am pc

von xxx x. (Firma: xxx) (shorty1990)


Lesenswert?

Ahh mist ich habe dein vorherigen Post zu spät gesehen.
Sorry wenn ich mich irre aber eigendlich dachte ich das ich das high 
interupt richtig "konfiguriert" habe

siehe hier:
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
void _high_ISR (void)
{
    _asm goto Interrupt_PWM _endasm
}

Laut meiner interpretation des Programmes müsste ich mit der zuvor 
angehängten Datei eine Pwm mit 20ms Periodenlänge und 1.5ms Duty Cycle
erzeugen.


PS:Ich weis schon was ein interrupt ist, allerdings heißt das nicht das 
ich es auch direkt fehlerfrei im Code anwenden kann.^^

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.