Hallo, habe einen PIC18f4550 mit 20MHz quarz. Ich versuche mit diesem nun 2 voneinander unabhängig arbeitende PWM-Signale zu erzeugen. Die PWM Signale gehen auf einen L293d welcher wiederum 2 Motoren ansteuert (3v Gleichstrom). Durch das PWM will ich nun die Drehzahl der Motoren regeln allerdings unabhängig voneinander. Wie erzeuge ich nun 2 voneinander unabhängige PWM Signale, welche ich allerding noch durch analoge Signale steuern kann (Fototransistoren). Die Signale der 2 Sensoren habe ich bereits eingelesen über den pin a0 & a1. Quellcode der sensoren: void main(void) // Beginn Hauptprogramm { ini(); while(1) { sensorBan=an; if (ADCON0bits.GO_DONE==0) { sbr=ADRESH; ADCON0bits.CHS0=1;// schaltet AN0 ein (sensor boden rechts) ADCON0bits.GO_DONE=1; } Delay10KTCYx(1); if (ADCON0bits.GO_DONE==0) { sbl=ADRESH; // schaltet AN1 ein (sensor boden links) ADCON0bits.CHS0=0; ADCON0bits.GO_DONE=1; } Delay10KTCYx(1); } Ich hoffe mir kann jemand helfen. mfg
Hi, hast du das Programm getestet? Wenn ja wie? Du verwendest nur das High-Byte des Ergebnisses vom AD-Wandler. Hast du das Ergebnis linksbündig in ADRESH und ADRESL drinstehen? Du verschenkst damit Auflösung. Lese doch beide Register aus und speichere sie dann in einer Variable, z.B. so unsigned short sbr; sbr = ( ADRESH << 8 ) | ADRESL; Dazu muß es aber rechtsbündig drinstehen. Zur PWM: Der Controller hat doch 2 Hardware PWM Module. Diese musst du zuerst konfugieren mit den richtigen Einstellungen wie z.B. Frequenz und so. Dann kannst du das PWM Verhältnis so wie du es willst in Abhängigkeit von deinen AD Werten immer wieder aktualisieren. Im Datenblatt steht es relativ genau drinnen, wie man vorgehen muss. Wenn du konkrete Fragen hast, schreibe wieder!
Danke für die schnelle Antwort. ich habe das ergebnis des ad linksbündig stehen und lese nur high aus. Dass mit der Auflösung ist grundsätzlich eine gute idee allerdings sehe ich für meine zwecke keinen großen sinn darin. Die 2 sensoren sollen nur eine schwarze linie erkennen aber trotzdem danke schonma für diese idee vllt werde ich sie noch brauchen. Ich habe mich schon durch das Datenblatt gekämpft allerdings komme ich da nicht weiter auf welcher seite steht es den beschrieben? mfg
Kapitel 15.4 PWM Mode (Seite 150) Die Ausgänge sind dann CCP1 (RC2) und CPP2 (RC1 oder RB3). Du hast ein "normales" PWM Modul, das nicht so kompliziert ist und ein enhanced PWM Module. Aber steht alles drinnen: 15.4.4 SETUP FOR PWM OPERATION The following steps should be taken when configuring the CCPx module for PWM operation: 1. Set the PWM period by writing to the PR2 register. 2. Set the PWM duty cycle by writing to the CCPRxL register and CCPxCON<5:4> bits. 3. Make the CCPx pin an output by clearing the appropriate TRIS bit. 4. Set the TMR2 prescale value, then enable Timer2 by writing to T2CON. 5. Configure the CCPx module for PWM operation. des englischen solltest du schon halbwegs mächtig sein...
hab mir grad nochmal des Programm angeschaut. Für was sind die Wartezeiten? Wahrscheinlich dafür, dass die Wandlung sicher zu Ende ist, ode? Ist so nicht schön gemacht. Du kannst auch das GOnDone Bit so lange abfragen bis es wieder null ist und dann erst weiter gehen. So wie ich es gemacht hab. Nennt sich polling. Noch schöner wäre es natürlich, wenn du das Ergebnis in einer Interrput Service Routine abspeicherst. Dann verbräts du nicht so viel Rechenzeit
1 | void main(void) // Beginn Hauptprogramm |
2 | {
|
3 | ini(); |
4 | |
5 | while(1) |
6 | {
|
7 | sensorBan=an; // ?? |
8 | |
9 | ADCON0bits.CHS0=0; // Kanal einstellen |
10 | ADCON0bits.GO_DONE=1; // Wandlung starten |
11 | |
12 | while (ADCON0bits.GO_DONE==0) continue; // warten bis Wandlung fertig |
13 | |
14 | sbr=ADRESH; // Ergebnis speichern |
15 | |
16 | ADCON0bits.CHS0=1; // Kanal wechseln |
17 | ADCON0bits.GO_DONE=1; // Wandlung starten |
18 | |
19 | while (ADCON0bits.GO_DONE==0) continue; // warten bis Wandlung fertig |
20 | |
21 | sbl=ADRESH; // schaltet AN1 ein (sensor boden links) |
22 | |
23 | }
|
Hallo, Hier mein Programm zur Erzeugung von PWM-Signalen an CCP1 pin RC0. Aber wie bekomme ich jetzt parallel dazu an CCP2 pin RC1 ein weiteres PWM-Signal? Über das CCPRxL Register kann ich ja jeweils die dc einstellen ?!? void main(void) // Beginn Hauptprogramm { TRISD=0x00; //Port D ausgang (L293d ports) TRISC=0x00; //Port C ausgang (L293d enableports) PORTB=0x00; //Port B clear (8 LEDs) PR2=0b11111111; // maximale periodendauer CCPR1L=0b00111111; //dc ccp1 pin CCPR2L=0b00111111; //dc ccp2 pin CCP1CON=0x0C; //PWM Mode ausgewählt CCP2CON=0x0C; //PWM Mode ausgewählt T2CON=0b01111001; //1:16 prostscale, Timer 2 off, Prescale = 4 T2CONbits.TMR2ON = 1; // Timer2 an while(1) { //anfang dauerschleife vorM1(); //motor1 vorwärts while (TNR2==CCPR1L) continue; //warten bis dc ccp1 erreicht einszweiEN=0; //Motor 1 enabled RC0 while (TNR2==PR2) continue; //warten bis maximale periodendauer erreicht einszweiEN=1; //Motor 1 disabled RC0 } //ende dauerschleife }
funktioniert denn schon der eine PWM Ausgang? Ich denke mal eher nicht... Ich glaube du verstehst da was grundsätzlich falsch. Du hast eine Hardware PWM in diesem Controller, das heißt du stellst die notwendigen Register ein wie du sie haben willst und dann läuft die PWM "von alleine" ohne dass du ständig in der while(1) irgendwas dafür tun mußt. Die Frequenz läßt man ja meist konstant und ändert nur bei Bedarf in der while(1) Schleife den duty_cycle. Über das CCPRxL und noch über 2 Bits im CCPXCON stellst du den duty_cycle ein (zusammen also 10-bit Auflösung). Du kannst auch nur über CCPRxL einstellen, hast dann halt nur 8 bit Auflösung. und wenn du Code postest, dann alles. Es weiß keiner was hier gemacht wird: vorM1(); Also, änder des erst mal ab und dann könnnen wir nach dem 2. PWM Ausgang schauen. Hast du die Möglichkeit des zu testen?
Hallo, also vorM1(); ist für euch nicht von Interesse. Da wird lediglich die Richtung der Motoren bestimmt. Also ich habe es schon mal getestet die Motoren drehen unterschiedlich schnell --> Funktioniert Jetzt bin ich aber nicht mehr weiter gekommen bei folgendem. Ich habe 2 Sensoren die über die 2 Eingänge A0 & A1 angeschlossen sind. Die Werte werden Analog ausgelesen und dann in einem 8 Bit Register gespeichert soweit richtig? Jetzt ist das CCPRxL Register auch 8 Bit lang. Ich habe versucht die werte die mir der AD-Wandler liefert direkt in die CCPRxL Register zu schreiben leider nimmt er diese nicht an. Hier mal der Quelltext:
1 | void ini (void) |
2 | {
|
3 | ADCON1=0b00001101; // AN0 & AN1 Analog |
4 | |
5 | TRISA=0xFF; // PortA eingang |
6 | TRISB=0x00; // PortB ausgang |
7 | TRISD=0x00; // PortD ausgang |
8 | TRISC=0x00; // PortC ausgang |
9 | |
10 | PORTB=0x00; // PortB gelöscht |
11 | |
12 | PR2=0xFF; // Maxiamale Periodendauer |
13 | |
14 | CCPR1L=0b01010111; // dc RC2-Pin Startwert |
15 | CCPR2L=0b01010111; // dc RC1-Pin Startwert |
16 | |
17 | CCP1CON=0b00111111; // PWM Mode ausgewählt |
18 | CCP2CON=0b00111111; // PWM Mode ausgewählt |
19 | |
20 | T2CON=0b00000100; // Timer 2 an, Vorteiler = 4 |
21 | |
22 | sensorBan=an; // Sensoren Boden an (Transistor) |
23 | vorM1(); // motor1 vorwärts |
24 | vorM2(); // motor2 vorwärts |
25 | |
26 | }
|
27 | |
28 | void main(void) // Beginn Hauptprogramm |
29 | {
|
30 | ini(); // aufruf der initialisierung; |
31 | |
32 | while(1) |
33 | { // anfang dauerschleife |
34 | |
35 | ADCON0bits.CHS0==0; // Kanal einstellen |
36 | ADCON0bits.GO_DONE=1; // Wandlung starten |
37 | |
38 | while (ADCON0bits.GO_DONE==0) continue; // warten bis Wandlung fertig |
39 | |
40 | sbr=ADRESH; // Ergebnis speichern |
41 | PORTB=sbl; // ausgabe der binärzahl an LED0..7 |
42 | CCPR1L=ADRESH; // dc für Motor2 anpassen |
43 | |
44 | |
45 | ADCON0bits.CHS0=1; // Kanal einstellen |
46 | ADCON0bits.GO_DONE=1; // Wandlung starten |
47 | |
48 | while (ADCON0bits.GO_DONE==0) continue; // warten bis Wandlung fertig |
49 | |
50 | sbl=ADRESH; // Ergebnis speichern |
51 | PORTB=sbl; // ausgabe der binärzahl an LED0..7 |
52 | CCPR2L=ADRESH; // dc für Motor1 anpassen |
53 | |
54 | } // ende dauerschleife |
55 | }
|
Jonas Kiefer schrieb: > ADCON0bits.CHS0==0; // Kanal einstellen da ist wohl ein = zuviel. Dann stellt er den Kanal 0 nicht ein. Ansonsten sieht auf den ersten Blick richtig aus. Der zweite Motor hat auch nicht funktioniert? Mit der Ausgabe, die du gemacht hast, kannst du ja sehen ob die AD-Wandlung richtig funktioniert. Mit welchen Gerät programmierst du?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.