Schrittmotor mit LCD, Aussetzer mit I2C

Hallihallo.

Ich bin Arduino-Anfänger und nutze eine Aufgabe zum lernen, anders geht es nicht.

Mein Wunsch ist, einen Schritmotor mit 2 Taster(oder Joystick),
vor und zurück zufahren. Ein weiterer Taster soll nacheinander die Wahl von drei
Geschwindigkeitstufen ermöglichen: Schnell, langsam, Einzelschritt.

Soweit würde ich das ja noch hinbekommen. Wichtig ist allerdings, das ein LCD die aktuelle
Position des Schrittmotors anzeigt und ein weiterer Taster das Resetten der jeweiligen
Position zulässt.

Problem ist einfach, wenn ich in der Motoransteuerungsschleife die Ausgabe an das LCD
mit einbaue, der Motor nicht mehr "rund" läuft.

Ja.... ich habe bereits gesucht und Hinweise gefunden, das das I2C Protokoll hier wohl die Bremse ist.
SPI wäre wohl eine Option mit der ich null Erfahrung habe. Viele angebotene SPI Displays sind in der
Regel sehr 'grafisch' was ich eigentlich nicht brauche. mir reicht ein 16x2,
mehr soll es auch nicht sein. Erstmal.

Hätte ich weniger Probleme, wenn ich wie damals das LCD über HD44780 anschließe?

mit den Ports müsste ich hinkommen...

Zeige uns doch erst mal Deinen Sketch (in Codetags).

Gruß Tommy

Hi

Ein normales LCD lässt sich mit 7 Pins ansteuern.

Was mir an Deinen Ausführungen nicht gefällt: MotoransteuerungsSCHLEIFE.
Also während der Motor in dieser Schleife drin steckt, passiert eh nichts Anderes - da braucht's dann auch keine großartige Anzeige auf dem LCD - Du kannst eh NICHTS daran ändern - oder fragst Du in der Schleife auch noch die Taster ab?

Also: Schleife weg - nutze loop() als Schleife (ist's eh schon).
Du musst 'nur' herausfinden, was Du 'in diesem Durchlauf' machen willst - unterm Strich ist Das dann ein endlicher Automat(eine Schrittkette/eine State-Maschine.
Dazu hat combie Mal was zusammen getragen.

Wenn Du Dein Sketch zeigen würdest, könnten wir Da ggf. auch das Eine oder Andere ausbessern.

MfG

Okok... :o

Eigentlich wollte ich euch den peinlichen "Basis"code vorenthalten... ^^

Vielen Dank, Andreas

#include <Wire.h>  
#include <LiquidCrystal_PCF8574.h>

LiquidCrystal_PCF8574 lcd(0x3F); // set the LCD address to 0x3F for a 16 chars and 2 line display


#define ena 12       // Pin 12 connected to Enabled pin on EasyDriver
#define step_pin 5   // Pin 9 connected to Steps pin on EasyDriver
#define dir_pin 4    // Pin 8 connected to Direction pin
#define MS1 10       // Pin 10 connected to MS1 pin
#define MS2 11       // Pin 11 connected to MS2 pin


//#define SLEEP 12      // Pin 12 connected to SLEEP pin

#define X_pin A3        // Pin A0 connected to joystick x axis
#define speed_switch 3  // Pin 4 connected to joystick switch

#define Limit01 8       // Pin 2 connected to Limit switch out
#define Limit02 9       // Pin 3 connected to Limit switch out

int step_speed=50;  // Speed of Stepper motor (higher = slower)
int step_zaehler=0;
int step_delay=0;

void setup() {

// I2C Aktivierung
   Wire.begin();
   Wire.beginTransmission(0x3F);



   pinMode(MS1, OUTPUT);
   pinMode(MS2, OUTPUT);
   pinMode(dir_pin, OUTPUT);
   pinMode(step_pin, OUTPUT);
   pinMode(ena, OUTPUT);
// pinMode(SLEEP, OUTPUT);
   
  pinMode(Limit01, INPUT_PULLUP);
  pinMode(Limit02, INPUT_PULLUP);
   
   pinMode(speed_switch, INPUT_PULLUP); 
   
//digitalWrite(SLEEP, HIGH);  // Wake up EasyDriver
   delay(5);  // Wait for EasyDriver wake up
   
    

   digitalWrite(ena, HIGH);


   lcd.setBacklight(255);
   lcd.home();
   lcd.clear();
   lcd.noCursor();
   lcd.setCursor(0, 0);
   lcd.print ("*TEST*");
   delay(1000);
   
}


void loop() {

    
    


  
  if (!digitalRead(speed_switch)) {  //  If Joystick switch is clicked
    delay(350);                      // delay for deboucing
    switch (step_speed) {            // check current value of step_speed and change it

      
      case 1:
        step_speed=50;
        step_delay=500;// slow speed
        lcd.home();
        lcd.clear();
        lcd.print (step_speed);
        break;
        
      case 3:
        step_speed=1;
        step_delay=0;// fast speed
        lcd.home();
        lcd.clear();
        lcd.print (step_speed);
        break;
        
      case 50:
        step_speed=3;
        step_delay=0;// medium speed
        lcd.home();
        lcd.clear();
        lcd.print (step_speed);
        break;
     
    }
  }    
    
  if (analogRead(X_pin) > 812) {  //  If joystick is moved Left 
    
    if (!digitalRead(Limit01)) {}  // check if limit switch is activated
    
      else {  //  if limit switch is not activated, move motor clockwise
      
        digitalWrite(dir_pin, LOW);  // (HIGH = anti-clockwise / LOW = clockwise)
        digitalWrite(step_pin, HIGH);
        delay(step_speed);
        delay(step_delay);
        digitalWrite(step_pin, LOW);
        delay(step_speed);
        lcd.setCursor(0, 0);
        step_zaehler = step_zaehler +1 ;
        lcd.setCursor(0, 1);
        lcd.print (step_zaehler);
    }      
  }
  
    if (analogRead(X_pin) < 212) {  // If joystick is moved right
    
    if (!digitalRead(Limit02)) {}  // check if limit switch is activated
    
     else {  //  if limit switch is not activated, move motor counter clockwise
      
        digitalWrite(dir_pin, HIGH);  // (HIGH = anti-clockwise / LOW = clockwise)
        digitalWrite(step_pin, HIGH);
        delay(step_speed);
        delay(step_delay);
        digitalWrite(step_pin, LOW);
        delay(step_speed);
        lcd.setCursor(0, 0);
        step_zaehler = step_zaehler -1 ;
        lcd.setCursor(0, 1);
        lcd.print (step_zaehler);
    }      
  }
         
}

Hätte ich weniger Probleme, wenn ich wie damals das LCD über HD44780 anschließe?

Äh...
Die einfachen LCD Modulen haben den HD44780 oder komplementäre als Controller/Ansteuerung der Anzeige.

Grüße Uwe

Hi

LCD-Befehle brauchen Zeit.
lcd.setCursor(0, 0); wird direkt mit anderen Koordinaten überschrieben - also unnötig.
Auch ist lcd.clear() eine sehr zeitintensive Möglichkeit, die drei zeichen vom Display runter zu bekommen - das DaBla des Display (oder eines HD44780) zeigt die typischen Wartezeiten, bis das Display damit fertig ist.
Je nachdem, wie die Lib gestrickt ist, WARTET Die, damit folgende Befehle nicht an einem 'blockiertem Display abprallen'.

Warum englische Kommentare, wenn's doch für Hilfe den deutschen Zweig bevorzugst?
Im englischsprachigem Bereich dürftest Du eine höhere Anzahl potentieller Helfer ansprechen.

MfG

Edit
@Uwe
Wenn Du den HD44780 aber 'zu Fuß' ansprichst - also z.B. 4-bit - bist Du nicht an den Takt von I²C gebunden - musst aber halt auch auf ALLES selber achten.
Klar, auch hier musst Du Dich an die Wartezeiten halten - kannst Die aber - millis() sei Dank - aber auch ohne delay() abfrühstücken.

Das Interface funktioniert mit 1MHz. In einem Register gibt es ein BUSY Flag, das ausgewertet werden müßte um zu warten damit man wieder Daten schicken kann. Da man sich aber beim Interface meist die R/W Leitung spart, und darum das Display nicht lesen kann, muß man das Timing auf der sicheren Seite halten und darum langsamer übertragen.

Grüße Uwe

Vielen Dank für eure Anmerkungen.

Ich hab jetzt anstatt des I2C Displays mal eins mit HD44780 angeschlossen,
leider hatte der Motor dann immernoch einen unruhigen Lauf.
Ich habe dann den code bis auf das nötigste ausgedünnt, also nur Motorbewegung
ohne Positionsanzeige auf Display, dann läuft der Motor wie ich es mir vorstelle.

Ich welche Richtung muss ich nun suchen um dort irgendwie die Positionsanzeige
auf das Display zu bekommen? Muss der Motor komplett anders angesteuert werden ?

#include <LiquidCrystal.h>

const int rs = 8, en = 9, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

#define ena 13           
#define step_pin 7       
#define dir_pin 6        

#define X_pin A2         
#define speed_switch 1   

#define Limit01 11       
#define Limit02 12       

int step_speed=1000;       
int step_zaehler=0;
int step_delay=0;

void setup() {


   pinMode(dir_pin, OUTPUT);
   pinMode(step_pin, OUTPUT);
   pinMode(ena, OUTPUT);
   
   pinMode(Limit01, INPUT_PULLUP);
   pinMode(Limit02, INPUT_PULLUP);
   
   pinMode(speed_switch, INPUT_PULLUP); 
   digitalWrite(ena, HIGH);

   
 
   lcd.begin(16,2);
   lcd.print ("*Test 1.1*");
   delay(1000);
  
}

void loop() {
    
  if (analogRead(X_pin) > 612) {  
    
    if (!digitalRead(Limit01)) {}  
    
      else {  
      
        digitalWrite(dir_pin, LOW);  
        digitalWrite(step_pin, HIGH);
        delayMicroseconds(step_speed);
        digitalWrite(step_pin, LOW);
        delayMicroseconds(step_speed);
        //step_zaehler = step_zaehler +1 ;
        //lcd.setCursor(0, 1);
        //lcd.print (step_zaehler);
    }      
  }
  
    if (analogRead(X_pin) < 412) {  
    
      if (!digitalRead(Limit02)) {}  
    
     else {  
      
        digitalWrite(dir_pin, HIGH);  
        digitalWrite(step_pin, HIGH);
        delayMicroseconds(step_speed);
        digitalWrite(step_pin, LOW);
        delayMicroseconds(step_speed);
        //step_zaehler = step_zaehler -1 ;
        //lcd.setCursor(0, 1);
        //lcd.print (step_zaehler);
    }      
  }
         
}

Vielen Dank, Andreas

packe mal deine LCD Ausgabe in eine extra Funktion und rufe sie nur alle 500ms auf

Hi

Du kannst den LCD-Aufruf auch aufsplitten.
Da Du den Takt mit übergibst, geht Das.
So sendest Du nur so viele Bits (bzw. Nibbles), wie Du Zeit hast.
Weiter macht Es keinen Sinn, die Anzeige viel öfter als 2x die Sekunden zu aktualisieren.

Ob Das die Lib bietet, also das Aufteilen der einzelnen Bytes, ist eher fraglich.
Für Fragen, wie so ein LCD intern tickt, gibt'sSprut.de.

MfG

Du könntest für die Ansteuerung des Steppers die MobaTools verwenden. Die erzeugen die Stepimpulse im Hintergrund per ISR und lassen sich vom I2C nicht stören.
Die Anzeige weniger oft zu aktualisieren bringt's auch nicht wirklich. Dann 'stolpert' der Stepper nur seltener :wink: . Es ist prinzipiell problematisch, die Stepimpulse im loop zu erzeugen, wenn dort Aufrufe enthalten sind, die rel. lang dauern - zumindest länger als die Zeit zwischen 2 Stepimpulsen.

N.B. Die MobaTools kannst Du über den Bibliotheksverwalter der IDE installieren