Hallo,
Ich habe eine Frage zu meinem Code(Board: Arduino Mega 2560).
Dieser rechnet die Position eines Motors durch Hall-Sensoren (schon original am Motor verbaut) relativ zum Endlagensensor aus. Jedoch hab ich das Problem dass der Arduino wenn der Motor schnell fährt die Position nicht mehr richtig ausrechnet und Werte verliert(?) und die Position somit nicht mehr stimmt. Liegt das daran dass der Code (evtl durch die Interrupts) zu langsam ist?
Hier der Code:
volatile int Hall1_X=0,Hall2_X=0,Hall3_X=0,Hall1_Z=0, Hall2_Z=0,Hall3_Z=0;
int Richtung_X, Richtung_Z, Position_X, Position_Z, Anschlag_X=0, Anschlag_Z=0, Ausgabespannung_X, Ausgabespannung_Z;
void setup() {
// put your setup code here, to run once:
TCCR2B = (TCCR2B & 0b11111000) | 0x01 ;
pinMode(9,OUTPUT); //Spannungsausgabe an SPS X-Achse (Positionierung)
pinMode(10,OUTPUT); //Spannungsausgabe an SPS Z-Achse (Positionierung)
pinMode(32,INPUT); //Endlagensensor X-Achse
pinMode(33,INPUT); //Endlagensensor Z-Achse
pinMode(2,INPUT_PULLUP); //Hall_1 Sensor Z-Achse
pinMode(18,INPUT_PULLUP); //Hall_2 Sensor Z-Achse
pinMode(19,INPUT_PULLUP); //Hall_3 Sensor Z-Achse
pinMode(3,INPUT_PULLUP); //Hall_1 Sensor X-Achse
pinMode(20,INPUT_PULLUP); //Hall_2 Sensor X-Achse
pinMode(21,INPUT_PULLUP); //Hall_3 Sensor X-Achse
attachInterrupt(digitalPinToInterrupt(3),ISR_HALL_1_X_C,CHANGE); //Interrupt für Hall_1 Sensor X-Achse
attachInterrupt(digitalPinToInterrupt(2),ISR_HALL_1_Z_C,CHANGE); //Interrupt für Hall_1 Sensor Z-Achse
}
void loop() {
// put your main code here, to run repeatedly:
Hall1_Z=digitalRead(2);
Hall2_Z=digitalRead(18); //Einlesen der Hall-Sensoren 2&3 der Z_Achse
Hall3_Z=digitalRead(19);
Hall1_X=digitalRead(3);
Hall2_X=digitalRead(20); //Einlesen der Hall-Sensoren 2&3 der X_Achse
Hall3_X=digitalRead(21);
Anschlag_X=digitalRead(32); //Einlesen der Endlagensensoren X & Z-Achse
Anschlag_Z=digitalRead(33);
if (Anschlag_X==HIGH)
{
Position_X=0;
}
if (Anschlag_Z==HIGH)
{
Position_Z=0;
}
Ausgabespannung_X=(25+Position_X);
analogWrite(9,Ausgabespannung_X);
Ausgabespannung_Z=(25+(Position_Z*2));
analogWrite(10,Ausgabespannung_Z);
}
//----------------------------------------------
void ISR_HALL_1_X_C ()
{
if (Hall1_X==1)
{
if (Hall2_X==1)
{
Richtung_X=1;
Position_X=Position_X+1;
}
else if (Hall3_X==1)
{
Richtung_X=2;
Position_X=Position_X-1;
}
}
}
//----------------------------------------------
void ISR_HALL_1_Z_C ()
{
if (Hall1_Z==1)
{
if (Hall2_Z==1)
{
Richtung_Z=1;
Position_Z=Position_Z+1;
}
else if (Hall3_Z==1)
{
Richtung_Z=2;
Position_Z=Position_Z-1;
}
}
}
Grundsätzlich:
Variablen/Datensätze, welche in ISR und im Hauptprogramm genutzt werden wollen, müssen als volatile deklariert werden.
Und im Hauptprogramm atomar ausgelesen werden.
Wird das nicht eingehalten, gibts keine gültigen Werte, sondern nur Zahlensalat.
Ok vielen Dank dann probier ich das mal aus...
aber was heißt 'atomar ausgelesen'?
Und hast du eine Ahnung warum das Programm die oben genannten Fehler hat?
Und hast du eine Ahnung warum das Programm die oben genannten Fehler hat?
Höchst vermutlich, weil der Programmierer weder die Variablen als volatile deklariert hat, noch sie atomar ausliest.
Auch werden in der ISR Werte verwendet, welche in loop() gelesen werden (die Hallxxx Dinger). Die können zu dem Zeitpunkt schon lange veraltet sein.
Deine ISR ist durch den Umweg über AttachInterrupt echt lahmarschig.
Die dutzende von push und pop sind unnötig, wenn man es geschickter anstellt.
Du hast ein anderes zusätzliches grundlegendes Problem mit deinem Kode.
Deine CHANGE Interrupts benutzen die letzten vom Hauptkode gelesen Werte,
das werden ziemlich regelmäßig die ungeänderten sein,
hast du das berücksichtigt?
Warum liest du die relevaten nicht in der ISR aus?
Was wäre denn eine andere möglichkeit? bin leider in c/c++ sehr neu und hab diese Funktion als einzige funktionierende Funktion für meine Anwendung gefunden...
Whandall:
Du kannst also die Komplexität deines Programms deutlich verkleinern,
wenn du für die Halls und die Richtungen Bytes verwendest.
Kannst du mir vielleicht ein Beispiel dafür geben?
Wenn man etwas umbenennt und nur an einer Stelle benutzte Variablen durch ihre Initialisierung ersetzt,
erhält man etwas das ich für leichter zu lesen halte, aber schau selbst.