PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM Initialisierung beeinflusst externe Interrupts



icebreaker
09.05.2015, 21:26
Hallo Roboternetz!

Ich versuche ein 2-rädriges Fahrzeug mit Rad-Encodern zu bauen.
Diese werden über Lichtschranken realisiert und alles funktioniert soweit super.

Also ich kann die Flanken des Encoders über einen Interrupt einlesen und daher die Anzahl der durchlaufenden "Löcher" über UART ausgeben.


Sobald ich jedoch einen beliebigen Timer für ein PWM Signal initialisiere funktioniert das nicht mehr ganz so.
Dann werden manchmal mehrere Flanken erkannt (oft 2 auf einmal oder ganz viele hintereinander) und der Encoder wird unbrauchbar.

Ich nutze ein Arduino Mega (ATMega 2560), und programmiere diesen mit dem AVR-GCC Compiler.
PWM funktioniert einzeln und auch die Interrupts funktionieren einzeln, zusammen jedoch leider nicht :D

hier der Code:


#include <avr/io.h> #include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "uart.h"




uint16_t counter_l=0,counter_r=0;
char s[10];




void PWM_Init(void){
TCCR3A = (1<<WGM30)|(1<<COM3A1)|(1<<COM3B1);
TCCR3B = (1<<WGM32)|(1<<CS31);
}


ISR(INT2_vect)
{
counter_l++;
uart_puts("Left: ");
uart_puts(itoa( counter_l, s, 10 ) );
uart_puts("Right: ");
uart_puts(itoa( counter_r, s, 10 ) );
uart_putc('\n');
}


ISR(INT3_vect)
{
counter_r++;
uart_puts("Left: ");
uart_puts(itoa( counter_l, s, 10 ) );
uart_puts("Right: ");
uart_puts(itoa( counter_r, s, 10 ) );
uart_putc('\n');
}


void interrupt_init(void){
DDRD &= ~(1<<2);
DDRD &= ~(1<<3);

EICRA = (1<<ISC21)|(1<<ISC31); //falling edge detection for ext.int2,ext.int3
EIMSK = (1<<INT2)|(1<<INT3); //turn on ext.int2,ext.int3
sei();
}


int main(void){
//OUTPUTS
DDRE |= (1<<3); //Motor ? PWM


DDRE |= (1<<4); //Motor ? PWM

//Pre Settings
//PWM_Init();


uart_init();
interrupt_init();

//OCR3A=0;
//OCR3B=0;

while(1){

}
return 0;
}

habt ihr eine Idee, was das Problem sein könnte?
Danke schon mal im voraus!

Gruß Lukas

markusj
09.05.2015, 21:37
Störungen durch das PWM-Signal die auf die Encoder zurückkoppeln (Motorendstufe -> Spanungseinbrüche oder -spitzen)?

Davon abgesehen: Es ist meistens keine gute Idee, in ISRs langsame Funktionen wie itoa oder gar blockierende Vorgänge wie die (ungepufferte) Ausgabe über Kommunikationsschnittstelle auszuführen.

mfG
Markus

icebreaker
09.05.2015, 21:40
Danke für die schnelle Antwort!

Nein das kann eigentlich nicht der Grund sein, da ich ja OCR3A/B noch auf 0 habe -> daher laufen die Motoren ja noch garnicht.
Oder denke ich da falsch?

Ja das ist mir bewusst, das sollte nur eine vorläufige Debugging Ausgabe sein. Sollte man das trotzdem auch beim debugging vermeiden?

Gruß Lukas

021aet04
09.05.2015, 22:44
Im Programm sehe ich soweit keinen groben Fehler (habe aber die genauen Register, ... nicht angeschaut).
Ich würde in der Hauptschleife die UART Übertragung machen. Im Interrupt eine variable setzen. Wenn diese gesetzt ist wird die Datenübertragung gestartet (= Minimierung des Datenverkehrs).

Was mir noch auffällt ist das du die variablen im Interrupt nicht als volatile hast. Infos findest du z.b. Bei www.mikrocontroller.net im Artikel gcc tutorial (bzw im Interrupt artikel).

PS: hast du ein oszi damit man sich etwas anschauen könnte?

MfG Hannes

icebreaker
10.05.2015, 00:01
Danke auch dir für deine Antwort!

ich hab jetzt das UART wie du sagtest in die main gepackt und die variablen als volatile.

Wenn ich PWM_Init() nicht aufrufe läuft alles wie es soll.
Sobald ich es tue geht immer noch alles schief.
Jetzt sind es mehrere 1000 Aufrufe der ISR, da ja die Zeitverzögerung vom UART nicht mehr da ist..

Ich habe leider kein Oszilloskop da :/ zur not könnte ich es aber mal mit zum Studium nehmen Montag, da hab ich die Möglichkeit.
Allerdings hab ich auch schon eine Hardwareentprellung mit 100nF dran, sodass das nach meinem Verständnis nicht mehr prellen sollte...

Der Zusammenhang mit der Initialisierung des PWMs ist wohl höhere Magie..

Gruß Lukas

021aet04
10.05.2015, 08:03
Mit dem Atmega 2560 habe ich noch nicht gearbeitet, jedoch bei den anderen mit denen ich gearbeitet habe habe ich noch nie solche Probleme gehabt.
Prellen hast du eigentlich nur bei mechanischen Schaltern. Du verwendest vermutlich eine Lichtschranke, dort gibt es soetwas nicht. Was ich mir nur vorstellen könnte ist das die Räder ganz leicht hin und her bewegen und somit die Lichtschranke ständig schaltet.

Du könntest noch versuchen eine direkte Verbindung zwischen INT Eingang und Masse machen (direkt am arduino). Dann hast du auch ausgeschlossen das du dir Störungen über die signalleitungen einfängst.

Du könntest auch eine Led am Eingang anschließen (eine superhelle wäre von Vorteil) . Wenn es flackert oder blinkt schaltet der INT.

MfG Hannes

icebreaker
10.05.2015, 10:02
Ich hab die Lösung!

Also warum das mit der Initialisierung Störung verursacht weiß ich nicht..
Nun schick ich das Signal durch einen Schmitt-Trigger, sodass ein klares Signal herauskommt und alles funktioniert..
Ich wusste leider bis eben grad noch nicht dass es ein solches Bauteil gibt..

Trotzdem danke für die vielen Antworten!

Gruß Lukas

021aet04
10.05.2015, 13:04
Was mir gerade aufgefallen ist. Du hast die internen Pullup Widerstände nicht eingeschaltet. Hast du externe? Wie schaut deine Schaltung aus?

Die internen Pullup Widerstände schaltest du ein indem du z.b. PORTB |= (1«PB1); schreibst jedoch muss der Pin als Eingang geschaltet sein.

Dann müsste das auch ohne externe ICs funktionieren.

MfG Hannes

icebreaker
10.05.2015, 14:22
30151

Durch den Pull-Down ist es klar definiert.
Ich denke das problem waren Spannungen um 2.6 V. Da kam es dann denke ich dazu, dass mehrere Flanken erkannt wurden.
durch den Schmitt-Trigger werden diese ja eliminiert..

MfG Lukas

021aet04
10.05.2015, 20:47
Was ist das für eine Lichtschranke? Bei einem Fototransistor kann man die Schaltung so machen wie du es hast. Bei einer fotodiode o.Ä. Brauchst du einen Komparator am besten mit Hyterese.

Aber wenn es soweit funktioniert dann passt es.

MfG Hannes