PDA

Επιστροφή στο Forum : Συνεχιση του κωδικα μετα το interrupt βοηθεια?



profilca
25-10-16, 21:01
Εχω την εξης εντολη interrupt στον κωδικα μου για να σταματω ενα stepper οταν χτυπηθει ενας διακοπης.
Η εντολη αυτη σταματα το μοτερ αλλα μετα δεν μπορω να συνεχισω στον κωδικα μου παρα μονο με reset.
Εχει κανεις καμμια ιδεα για το πως να συνεχιζει ο κωδικας στην loop?
Το κομματι του κωδικα για το interrupt ειναι το παρακατω



const int BUTTON = 21; // INTERRUPT BUTTON
void setup(void) {

pinMode (BUTTON, INPUT_PULLUP);
digitalWrite (BUTTON,HIGH);
attachInterrupt (2, switchPressed, CHANGE); // see https://www.arduino.cc/en/Main/ArduinoBoardMega2560 for No of pins(it's first No,here is 0-pin 2) // External Interrupts: 2 (interrupt 0), 3 (interrupt 1), 18 (interrupt 5), 19 (interrupt 4), 20 (interrupt 3), and 21 (interrupt 2).
// These pins can be configured to trigger an interrupt on a low level, a rising or falling edge, or a change in level.
}

// Interrupt Service Routine (ISR)
void switchPressed ()
{

while (digitalRead (BUTTON) == LOW)

stepper.stop();
}

klik
25-10-16, 21:16
Γιατί επαναλαμβάνεις τόσες φορές το stepper.stop(); Φοβάσαι μήπως δεν το καταλάβει με την πρώτη φορά;
Πως περιμένεις να ξαναρχίσει μετά το σταμάτημα (με τί τρόπο);
Γιατί κάνεις interrupt στο change και όχι στο low;
Η stepper.stop() επιτρέπεται να κληθεί δεύτερη φορά ή τα κάνει μαντάρα;
Έχει τόσο απλό κώδικα που να μπορεί να κληθεί μέσα απο interrupt ή τα κάνει μαντάρα;

profilca
25-10-16, 21:26
Γιατί επαναλαμβάνεις τόσες φορές το stepper.stop(); Φοβάσαι μήπως δεν το καταλάβει με την πρώτη φορά;
Πως περιμένεις να ξαναρχίσει μετά το σταμάτημα (με τί τρόπο);
Γιατί κάνεις interrupt στο change και όχι στο low;
Η stepper.stop() επιτρέπεται να κληθεί δεύτερη φορά ή τα κάνει μαντάρα;
Έχει τόσο απλό κώδικα που να μπορεί να κληθεί μέσα απο interrupt ή τα κάνει μαντάρα;

Κατα την γνωμη σου πως θα πρπει να ειναι ο κωδικας σ'αυτο το σημειο για να μπορει να συνεχει την κυριως λουπα?
Οσο για το change και το low ενταξει μπορει να αλαγχθει αν και δουλευει και ετσι

klik
26-10-16, 01:12
// Interrupt Service Routine (ISR)
void switchPressed ()
{

if(digitalRead (BUTTON) == LOW)

stepper.stop();
}


α) Δεν ξέρω τι λειτουργίες εκτελεί η stepper.stop() αν την εχεις γραψει εσυ, ανεβασε τη. Αν ειναι πολυπλοκη, θα πρεπει να βγει εξω απο το interrupt.
β) δεν ξερω αν τα interrupt του arduino είναι πραγματικά ή software interrupts
γ) δεν ξέρω από arduino

picdev
26-10-16, 08:42
Έχει κλάσεις το Arduino ?

nkarama
26-10-16, 10:22
Έχει κλάσεις το Arduino ?

C++ είναι, γιατί να μην έχει? 'αλλωστε, όλες (οι περισσότερες) οι βιβλιοθήκες τι είναι, κλάσεις είναι...

kioan
26-10-16, 10:26
Έχει κλάσεις το Arduino ?

Οι βιβλιοθήκες του Arduino (http://playground.arduino.cc/Code/Library) είναι στην ουσία κλάσεις και ακολουθούν τη σύνταξη της C++.



(με πρόλαβε ο προλαλήσας :001_smile:)

Fire Doger
26-10-16, 11:20
Γιατί δεν το σκέφτεσαι βήμα βήμα?

Πάει παει το μοτερ....
Χτυπάει τερματικό το οποίο δίνει low
Μπαίνει σε interrupt.
Όσο είναι low δηλαδή πατημένο το τερματικό σταμάτα. Δηλαδή για πάντα εφόσον η εντολή εκτελέστηκε επειδή πατήθηκε το τερματικό....

Έστω οτι αφαιρεις το while.
Χτυπάει τερματικό σταματάει.
Του λες πανε από την άλλη, μολις ξεπατηθει το τερματικό θα σταματήσει ξανά.

Βγάλε το while, αλλαξε το interrupt σε falling edge και πες μας τι κάνει. Λειτουργεί και το if του klik αλλά θα εχεις άσκοπα interrupt.

Για σκεψου έτσι όπως το έχεις τι θα γίνει αν χτυπήσει τερματικο, σταματήσει και το στειλεις ξανά στην ιδια κατεύθυνση. Όχι κάτι ευχάριστο αν δεν ελεγχεις αν είναι πατημένο κάποιος τερματικός καθέ φορά που κάνεις εκκίνηση...

Μπορείς και να κρατήσεις το change και να παίζεις με σημαία που θα ανεβοκατεβαζεις ανάλογα στις παρυφές και θα ελεγχεις την σημαία κατά την εκκίνηση.

cdesp
26-10-16, 12:10
Καλό είναι ηwhile να γίνει if. Αν θες όταν αφήνεις το κουμπί να ξανά ξεκινάει τότε η μέσα στο interrupt θα βάλεις μια else στην if όπου θα ξανά ξεκινάς το moter όπως στο setup, η να βάλεις και την συνάρτηση loop που λείπει και η οποία εκτελείται συνεχώς σε αντίθεση με την setup που εκτελείται μια φορά. Εκεί μπορείς επίσης να ελέγχεις την κατάσταση του κουμπιού και να πράξεις ανάλογα.

SProg
26-10-16, 12:44
Δεν καλουμε συναρτησεις ΠΟΤΕ μεσα σε interrupt.Κρατα το ποτε.

Καλουμε ΜΟΝΟ οταν ξερουμε ακριβως τι κανουμε,στη περιπτωση σου δεν ξερεις τι εκτελει το σκελος της συναρτησης που καλεις όυτε υποθετω αν μπερδευεται ο compiler.

picdev
26-10-16, 13:52
Αυτό που θυγετε είναι το retrancy , δεν σε αφήνει ο compiler να τις καλέσεις και από τη Main και από το interrupt . Και από το interrupt να τη καλέσεις δεν υπάρχει κανένα πρόβλημα .
Υπάρχουν και controller που έχουν stack για τις συναρτήσεις τότε κάλεις και από τα 2 πχ dspic και pic32 κτλ.
Το προβλημα είναι ότι όταν καλέσεις τη συνάρτηση στη μαιν θα έχει κοινά δεδομένα με αυτή που θα τρέξει στο ιντεραπτ

SProg
26-10-16, 16:20
To re-entrancy μηπως εννοείς;Εαν ναι,τοτε αυτο εννοω οτι ο Compile μπορει να μπερδευεται.

Γιατι δεν βαζεις απλα ενα Flag οταν ερχεται η διακοπη και να καλεις απο main;

xmaze
26-10-16, 18:35
αφου έχεις τον interrupt να ενεργοποιήται όταν πατάς το κουμπί για ποιόν λόγο εχεις την while ξανά να ελέγχει το πάτημα του κουμπιού;

ενδεχομένως να μποκάρει στην while γιατί το κουμπί έχει γίνει πάλι high μεσα στον interupt

profilca
26-10-16, 19:53
Γιατί δεν το σκέφτεσαι βήμα βήμα?

Πάει παει το μοτερ....
Χτυπάει τερματικό το οποίο δίνει low
Μπαίνει σε interrupt.
Όσο είναι low δηλαδή πατημένο το τερματικό σταμάτα. Δηλαδή για πάντα εφόσον η εντολή εκτελέστηκε επειδή πατήθηκε το τερματικό....

Έστω οτι αφαιρεις το while.
Χτυπάει τερματικό σταματάει.
Του λες πανε από την άλλη, μολις ξεπατηθει το τερματικό θα σταματήσει ξανά.

Βγάλε το while, αλλαξε το interrupt σε falling edge και πες μας τι κάνει. Λειτουργεί και το if του klik αλλά θα εχεις άσκοπα interrupt.

Για σκεψου έτσι όπως το έχεις τι θα γίνει αν χτυπήσει τερματικο, σταματήσει και το στειλεις ξανά στην ιδια κατεύθυνση. Όχι κάτι ευχάριστο αν δεν ελεγχεις αν είναι πατημένο κάποιος τερματικός καθέ φορά που κάνεις εκκίνηση...

Μπορείς και να κρατήσεις το change και να παίζεις με σημαία που θα ανεβοκατεβαζεις ανάλογα στις παρυφές και θα ελεγχεις την σημαία κατά την εκκίνηση.


const int BUTTON = 21; // INTERRUPT BUTTON
void setup(void) {

pinMode (BUTTON, INPUT_PULLUP);
digitalWrite (BUTTON,HIGH);
attachInterrupt (2, switchPressed, FALLING); // see https://www.arduino.cc/en/Main/ArduinoBoardMega2560 for No of pins(it's first No,here is 0-pin 2) // External Interrupts: 2 (interrupt 0), 3 (interrupt 1), 18 (interrupt 5), 19 (interrupt 4), 20 (interrupt 3), and 21 (interrupt 2).
// These pins can be configured to trigger an interrupt on a low level, a rising or falling edge, or a change in level.
}
void loop(){
// ΜΕΤΑΚΙΝΕΙ ΤΟ STEPPER ΣΕ ΔΙΦΟΡΕΣ ΘΕΣΕΙΣ ΣΕ mm

}
// Interrupt Service Routine (ISR)
void switchPressed ()
{

digitalRead (BUTTON == LOW);

stepper.stop(); //Ο ΔΙΑΚΟΠΤΗΣ ΣΤΑ 2600 mm
stepper.moveTo(2490);
}


Κατι τετοιο ενοεις? Πρεπει να βαλω κατι αλλο?
Εαν υποθεσουμε οτι o διακοπτης ειναι στα 2600 mm

SProg
26-10-16, 20:11
Πως ξερεις οτι δεν εκτελει την διακοπη δεκαδες φορές λογω Debounce και τρελενεται το Servo;

Δεν καταλαβαινω τι κανει αυτο: digitalRead (BUTTON == LOW);

klik
26-10-16, 21:15
Μεσα σε ιντεραπτ δεν μπορεις να βαζεις χρονοβορες λειτουργιες οπως μετακινηση στεπερ. Επισης το digitalRead σου ειναι λαθος. Διαβαζει την ακιδα 0 ή την 1 και πεταει το αποτελεσμα

SProg
26-10-16, 21:21
Μεσα σε ιντεραπτ δεν μπορεις να βαζεις χρονοβορες λειτουργιες οπως μετακινηση στεπερ. Επισης το digitalRead σου ειναι λαθος. Διαβαζει την ακιδα 0 ή την 1 και πεταει το αποτελεσμα

Δεν ειναι πανακεια βεβαια αυτο,απλα πρεπει να ξερεις τι κανεις και να εισαι προσεκτικος.


Για να μπει στο Vector σημαινει οτι ηρθε διακοπη οποτε δεν χρειαζεται να διαβαζεις παλι το Pin.Κανε '1' ή '0' ενα Flag και στη main() σου κανε μετα οτι θελεις.

profilca
27-10-16, 20:42
Δεν ειναι πανακεια βεβαια αυτο,απλα πρεπει να ξερεις τι κανεις και να εισαι προσεκτικος.


Για να μπει στο Vector σημαινει οτι ηρθε διακοπη οποτε δεν χρειαζεται να διαβαζεις παλι το Pin.Κανε '1' ή '0' ενα Flag και στη main() σου κανε μετα οτι θελεις.

Εαν κανω μια Flag θα αφησω stepper.stop(); η θα χρησιμοποιησω state = !state; ?


#include <Stepper.h>

int BUTTON = 21; // INTERRUPT BUTTON
volatile int state = HIGH;
volatile int must_spin=0; //δημιουγω μια flag για να βλέπω πότε μπηκα στο interrupt volatile για να μην έχω πρόβλημα με τα optimization




AccelStepper stepper(1, A0, A1); // 1 = Easy Driver interface
// Arduino A0 connected to STEP pin of Easy Driver
// Arduino A1 connected to DIR pin of Easy Driver


void setup()
{
stepper.setMaxSpeed(200); // Not to fast or you will have missed steps
stepper.setAcceleration(50); // Same here
pinMode (BUTTON, INPUT_PULLUP);
attachInterrupt (2, switchPressed, FALLING);
}


void loop()
{
digitalWrite(BUTTON, state);
if(must_spin) // ελεγχουμε συνεχώς εαν πρεπει να κινηθει το μοτερ και εφοσον πρεπει
{
stepper.step(100); //το κινούμε
must_spin=0; //και του λέμε κιόλας οτι οκ καναμε το βήμα που θέλαμε μην κάνεις άλλο βήμα
}
}


void switchPressed()
{
state = !state;
must_spin=1; //οταν μπω στο interrupt η flag θέτω ασσο στην μεταβλητή άρα το μοτερ πρέπει να κινηθει


}