Accelstepper und TFT_eSPI stören sich gegenseitig?!

Moin,

ich bin gerade dabei ein paar Puzzleteile zusammenzusetzen.

Das ganze läuft auf einem nodeMCU ESP8266.
Ich habe einen Stepper Motor mit einem DRV8825 Treiber
Dann habe ich einen AS5600 Encoder und einen TCS34725 Farbsensor.
Und ein 3,5" Display.

Verdrahtet ist das folgendermaßen:
AS5600 SCL an GPIO5 (I²C)
AS5600 SDA an GPIO4 (I²C) auf der Adresse 0x36

TCS34725 SCL an GPIO5 (I²C)
TCS34725 SDA an GPIO4 (I²C) auf der Adresse 0x29

DRV8825 STEP an GPIO12
DRV8825 DIR an GND

3,5" Display DC an GPIO0
3,5" Display RST an GPIO2
3,5" Display SCK an GPIO14
3,5" Display MOSI an GPIO13
3,5" Display CS an GPIO15

Und natürlich die entsprechenden GND, 5V und 3,3V angeschlossen.

Soweit so gut.
Jede Komponente funktioniert erwartungsgemäß einwandfrei, wenn ich ein paar Testsketche laufen lasse.

Nun möchte ich aber alles zusammenbringen und habe einen komplett jungfräulichen Sketch aufgemacht und angefangen die Codesegmente nach und nach aus meinen funktionierenden Sketchen zusammen zu kopieren.

Und da war dann relativ schnell Schluss:
Der Stepper funktioniert.
Der Encoder funktioniert.
Wenn ich jedoch das Display anspreche funktioniert der Stepper nicht mehr?!
Irgendetwas aus dem Display Code stört den Stepper Code.
In dem Moment, wo ich das Display initialisiere tut der Stepper nichts mehr?!

Ist die Zeile: “tft.init();” aktiv, funktioniert der Stepper nicht mehr.
Ist die Zeile: “//tft.init();” auskommentiert, funktioniert der Stepper wie erwartet.

Woran liegt das und was kann man da tun?

#include <AccelStepper.h>
#include <AS5600.h>
#include <Wire.h>
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include <Adafruit_TCS34725.h>
#define STEPpin  12
#define DIRpin   0
#define Microstepping 4                    // Stepperdriver is set to 1/n microsteps (here 1/4)
#define StepperStepsPerRevolution 200           //one revolution of the stepper is 200 steps
int StepsPerRevolution = (StepperStepsPerRevolution * Microstepping);       // results in 800 steps per one revolution of the stepper
unsigned long currentMillis;
long EncoderPos;
long StepperPos;
int p;
int mx;
int my;
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_700MS, TCS34725_GAIN_1X);
AS5600 encoder;
AccelStepper stepper(AccelStepper::DRIVER, STEPpin, DIRpin);
TFT_eSPI tft = TFT_eSPI();       // Invoke custom library
void setup() {
  Wire.setClock(400000L);
  Serial.begin(115200);
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  delay(100);
  Serial.println("");
  mx = tft.width();
  my = tft.height();
  Serial.print(mx);
  Serial.print(" ");
  Serial.println(my);
}
void loop() {
  currentMillis = millis();
  stepper.run();
  p--;
  EncoderPos = encoder.getPosition();
  StepperPos = stepper.currentPosition();
  Serial.print(" p:");
  Serial.print(p);
  Serial.print(" EncoderPos:");
  Serial.print(EncoderPos);
  Serial.print(" StepperPos:");
  Serial.print(StepperPos);
  Serial.println("");
  stepper.moveTo(p);
  delay(200);
}

Hi

Schuss ins Blaue: SPI und AccelStepper benutzen den gleichen Timer - sagen die ausführlichen Meldungen was dazu?

MfG

sagen die ausführlichen Meldungen was dazu?

die krieg ich WIE an?

-> Voreinstellungen
-> Compiler-Warnungen
->"Alle"

Oder wie?

...aahhh, nu gefunden:
-> Voreinstellungen
Ausführliche Ausgabe während Kompilierung -> checked

leider 49.133 Zeichen...

ich kürz das mal ein....

ich hab’s jetzt mal ungekürzt gelassen und stattdessen als Anhang hochgeladen

Ich konnte da jetzt nichts verdächtiges entdecken :frowning:

ausfuehrliche Meldungen.txt (47.8 KB)

postmaster-ino:
SPI und AccelStepper benutzen den gleichen Timer

Die AccelStepper benutzt keinen Timer ( Deshalb läuft sich auch praktisch auf allen Arduinos ) und SPI braucht üblicherweise auch keinen.

Pin12 beim Stepper verwendet, ist auch SPI_MISO? Oder gegebenfalls Nodemcu Pinorder tauschen.

Hammer Idee! Da hätte ich so schnell nicht gesucht. Nicht schlecht. Da bin ich nicht drauf gekommen. Aber klar, logisch. Hab ich sofort geprüft.
In der Setup Datei des Displays ist folgendes eingestellt:

// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
// Typical setup for NodeMCU ESP-12 is :
//
// Display SDO/MISO  to NodeMCU pin D6 (or leave disconnected if not reading TFT)
// Display LED       to NodeMCU pin VIN (or 5V, see below)
// Display SCK       to NodeMCU pin D5
// Display SDI/MOSI  to NodeMCU pin D7
// Display DC (or AO)to NodeMCU pin D3
// Display RESET     to NodeMCU pin D4 (or RST, see below)
// Display CS        to NodeMCU pin D8 (or GND, see below)
// Display GND       to NodeMCU pin GND (0V)
// Display VCC       to NodeMCU 5V or 3.3V
//
// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin
//
// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more
// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS
// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin
// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected.
//
// The NodeMCU D0 pin can be used for RST
//
// See Section 2. below if DC or CS is connected to D0
//
// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin
// If 5V is not available at a pin you can use 3.3V but backlight brightness
// will be lower.

// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ######

// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
#define TFT_CS   PIN_D8  // Chip select control pin D8
#define TFT_DC   PIN_D3  // Data Command control pin
#define TFT_RST  PIN_D4  // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST  -1  // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V

#define TOUCH_CS PIN_D1     // Chip select pin (T_CS) of touch screen, also define SPI frequency in Section 5 below

//#define TFT_WR PIN_D2    // Write strobe for modified Raspberry Pi TFT only

// ESP32 Dev board (planned, not supported yet)
//#define TFT_CS   5  // Chip select control pin
//#define TFT_DC   2  // Data Command control pin
//#define TFT_RST  4  // Reset pin (could connect to Arduino RESET pin)
//#define TFT_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST

Hier ist TOUCH_CS auf D1 = GPIO5 gesetzt, was ja gleichzeitig mein I²C SCL ist.

Ich habe jetzt mal testweise #define TOUCH_CS PIN_D1

auskommentiert: //#define TOUCH_CS -1
oder
mit -1 definiert: #define TOUCH_CS -1
und jeweils gespeichert und neu kompiliert.

Beides ergibt leider keine Änderung.
Sobald die Zeile: "tft.init();" aktiv ist, funktioniert der Stepper nicht mehr.

Das Display ist ja so angeschlossen?

SPI CLK = GPIO14
SPI MOSI = GPIO13
SPI MISO = GPIO12

Aus deinem Code:
#include <Adafruit_TCS34725.h>
#define STEPpin 12

12 = GPIO12 = D6

EDIT:
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;

// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT)

Moin,

woher nimmst du die Information dass MISO vom Display an GPIO12 angeschlossen ist?

Der MISO Anschluss am Display ist nirgendwo angeschlossen.
Bisher ist das nicht nötig, da ich keine Touch Funktion benutze.

An GPIO12 ist der STEP Eingang des DRV8825 angeschlossen, sonst nichts.

Hier noch die Pinbelegung [Quelle: TFT_eSPI/Tools at master · Bodmer/TFT_eSPI · GitHub]
TFT_eSPI/RPi_TFT_Connections.png at master · Bodmer/TFT_eSPI · GitHub

Lieben Gruß,
Chris

dann drehe die initialisierung um -.-.

initialisiere zuerst das Display, dann den Stepper.. dann wird das möglicherweise anders priorisiert..

Du kannst ja nicht verhindern das die Display Lib beim Init D6 vorbelegt oder die verwendung uminitialisiert.

Ist halt nure eine Idee.

Und du bist Dir sicher dass, wenn die HW SPI aktiviert ist, du trotzdem frei über den MISO-Pin verfügen kannst?
Da gabs nämlich schon probleme, dass da kein freier Zugriff mehr auf die PINs der HW-SPI z.B. durch digitalWrite bestand, sobald die HW SPI aktivirt ist.

Deltaflyer:
Und du bist Dir sicher dass, wenn die HW SPI aktiviert ist, du trotzdem frei über den MISO-Pin verfügen kannst?

Ich kenne speziell den ESP8266 nicht so gut. Aber bei allen anderen Microcomputern die ich kenne ist es so: Wenn eine spezielle HW ( SPI, I2C, Uart ... ) aktiviert wird, werden die zugehörigen Ausgangspins mit dieser internen HW verbunden. Der Zugriff über die 'Standard-IO' Funktion ist dann nicht mehr möglich. Ob ein spezieller Pin dieser HW im konkreten Fall benötigt wird oder nicht ist dabei egal.
Würde mich wundern, wenn das beim ESP anders wäre.

MicroBahner:
Ich kenne speziell den ESP8266 nicht so gut. Aber bei allen anderen Microcomputern die ich kenne ist es so: Wenn eine spezielle HW ( SPI, I2C, Uart ... ) aktiviert wird, werden die zugehörigen Ausgahttps://forum.arduino.cc/index.php?topic=634861.0ngspins mit dieser internen HW verbunden. Der Zugriff über die 'Standard-IO' Funktion ist dann nicht mehr möglich. Ob ein spezieller Pin dieser HW im konkreten Fall benötigt wird oder nicht ist dabei egal.
Würde mich wundern, wenn das beim ESP anders wäre.

Ich kenne den ESP8266 auch nicht wirklich, weiss aber, dass eben bei den andern Controllern die HW-SPI Pins eben nicht mehr für was anderes verfügbar sind, sobald / solange die HW-SPI aktiviert ist.

Genau darum hab ich ja diese Frage an den TO gestellt, ob er sich da sicher ist, diesen Pin einfach so für was anderes nutzen zu können.

Wer weiss, vielleicht merkt die Accelstepper ja, dass sie diesen Pin nicht mehr richtig ansteuern kann, und streikt deshalb, sobald das Display initialisiert wird.

Deltaflyer:
Wer weiss, vielleicht merkt die Accelstepper ja, dass sie diesen Pin nicht mehr richtig ansteuern kann, und streikt deshalb, sobald das Display initialisiert wird.

Sie wird es wohl noch nicht einmal merken. Ihre Ausgaben gehen einfach ins Leere ...

Ja , vielleicht hat auch der Motortreiber was dagegen, wenn sein DIR Eingang plötzlich auf nem Pin hängt, der nicht mehr Ausgang, sondern Eingang ist, und verweigert deshalb den Dienst.

kann mir gut vorstellen, dass auf diesen mikro-treiberplatinchen nur noch das allernötigste drauf ist, und dann eben so Dinge wie PullUp's / PullDown's eingespart werden und deshalb, wenn ein Eingang mal in der Luft hängt, schlicht weg nicht funktionieren.

Sie wird es wohl noch nicht einmal merken. Ihre Ausgaben gehen einfach ins Leere ...

Das scheint zu stimmen, denn stepper.currentPosition(); meldet einen laufenden Stepper zurück. encoder.getPosition(); meldet jedoch, das sich nichts dreht.

Deltaflyer:
Ja , vielleicht hat auch der Motortreiber was dagegen, wenn sein DIR Eingang plötzlich auf nem Pin hängt, der nicht mehr Ausgang, sondern Eingang ist, und verweigert deshalb den Dienst.

kann mir gut vorstellen, dass auf diesen mikro-treiberplatinchen nur noch das allernötigste drauf ist, und dann eben so Dinge wie PullUp's / PullDown's eingespart werden und deshalb, wenn ein Eingang mal in der Luft hängt, schlicht weg nicht funktionieren.

In meinem Eingangspost steht:

DRV8825 DIR an GND

dann drehe die initialisierung um -.-.

initialisiere zuerst das Display, dann den Stepper.. dann wird das möglicherweise anders priorisiert..

meinst du so?
Aus

AccelStepper stepper(AccelStepper::DRIVER, STEPpin, DIRpin);
TFT_eSPI tft = TFT_eSPI();       // Invoke custom library

habe ich jetzt

TFT_eSPI tft = TFT_eSPI();       // Invoke custom library
AccelStepper stepper(AccelStepper::DRIVER, STEPpin, DIRpin);

gemacht.

Hat leider nichts gebracht.

Nun habe ich GPIO12 für den STEP Pin durch GPIO2 ersetzt. Nun funktioniert es.

Sieht also tatsächlich so aus, als ob entweder die TFT Library fest GPIO12 für MISO benutzt und man dies auch nicht ändern kann?

Oder wenn SPI aktiviert ist, GPIO12 nichts anderes mehr machen kann als MISO?

Lieben Gruß,
Chris

Oh, ich Hornochse, ich hab mich verlesen, hab geglaubt, DIR sei an GPIO12. Na wenns der Step war, dann ist die Sache erst recht klar! Wenn du den STEP Eingang des Treibers praktisch in die Luft hängst, woher soll der Treiber denn wissen, dass er dem Motor Schritte senden soll.

Das ist, wie wenn Du dir zum Sprechen das Mikrofon ans Ohr hältst.