4 x MCP23S17 über SPI ansteuern, wie erstelle ich einen Sketch hierfür

so könnte es ca aussehen mit einer leeren dummy MCP Klasse zum testen:

class MCP23S17
{

};

class MCP23S17 mcp23S17_1;
class MCP23S17 mcp23S17_2;
class MCP23S17 mcp23S17_3;
class MCP23S17 mcp23S17_4;

class Motor
{
  protected:
    MCP23S17 &step;
    byte stepPin;
    MCP23S17 &dir;
    byte dirPin;
    MCP23S17 &sigIn;
    byte sigInPin;
    MCP23S17 &sigOut1;
    byte sigOutPin1;
    MCP23S17 &sigOut2;
    byte sigOutPin2;
    MCP23S17 &sigOut3;
    byte sigOutPin3;    
  public:
    Motor (MCP23S17 &step, byte stepPin,
           MCP23S17 &dir, byte dirPin,
           MCP23S17 &sigIn, byte sigInPin,
           MCP23S17 &sigOut1, byte sigOutPin1,
           MCP23S17 &sigOut2, byte sigOutPin2,
           MCP23S17 &sigOut3, byte sigOutPin3) :
      step(step), stepPin(stepPin),
      dir(dir), dirPin(dirPin),
      sigIn(sigIn), sigInPin(sigInPin),
      sigOut1(sigOut1), sigOutPin1(sigOutPin1), 
      sigOut2(sigOut2), sigOutPin2(sigOutPin2), 
      sigOut3(sigOut3), sigOutPin3(sigOutPin3)
    {}
};

Motor motor1 (mcp23S17_1, 7, mcp23S17_1, 15, mcp23S17_2, 7, mcp23S17_2, 15, mcp23S17_3, 15, mcp23S17_4, 15);

void setup() {}

void loop() {}

ob man dann schlussendlich die MCP Referenzen wirklich auch mehrmals übergeben will, oder sich lieber für immer und ewig an das Hardwaredesign binden will, kann man ja noch entscheiden. Dem ESP werden die 2 "doppelten" Referenzen egal sein

Hier mal das Pin Assignment für die MCP's.

und hier das Pin Assignment des ESP32

Ich hoffe die das Bild ist jetzt besser.

es wird hier immer runter skaliert, das Original hat 4000x2400 pxl Auflösung

ich versuche es mal mit einem Teil-Ausschnitt

Wie habe ich das zu verstehen. Willst Du Stepimpulse für 6 Motore mit 400kHz erzeugen - über die MCP23S17?

Hallo,

nicht ganz es sind 8 Motoren sowie 6 Referenzeingänge für Hallsensoren / Referenzschalter. Die AC Servo-Driver können mit bis zu 400Khz angesteuert werden, habe aber bisher nur so 120-200khz im Gebrauch.

Ich habe die mcp23s17 deswegen gewählt weil die bis zu 10Mhz theoretisch über SPI können. Der I2C mcp23017 ist dafür ungeeignet aus meiner Sicht.

Wie geschrieben der Controller2 mit Esp32 und einem MCP23S17 funktioniert ja und hat beim Testen mit 400khz auch keine Probleme gehabt, auch hier als Hintergrund weshalb die MCP's am HSPI des esp32 hängen und nicht am VSPI. Im Code ist auch zu sehen das hier auch die 2 Kerne Berücksichtigung finden.

Bei den MCP23S17 libraries hatte ich verschiedene durchprobiert einzig sinnvolle aus meiner Sicht ist die MajenkoLibraries/MCP23S17 welche ich auch beim Controller 2 Code eingebunden habe

Das gilt aber für den Bit-Takt. Um ein GPIO-Register zu addressieren sind bereits 16 Bit notwendig, mit dem Datenbyte weitere 8 Bit. Das sind dann schon 24 Takte = 2,4µs bei 10MHz. Um das Bit wieder auszuschalten braucht es mindestens ein weiteres Byte, für einen kurzen Impuls von 0,8µs also 3,2µs für die reine Datenübertragung.
Wie Du da bei 4 MCP's noch auf 200-400kHz am GPIO-Pin kommen willst, ist mir ein Rätsel.

Hi, im umkherschluss soll das bedeuten, daß das Design geändert werden müsste das jeder mcp einen eigenen SS hat? Nicht alle gpio werden die ganze Zeit voll angesteuert, relevant sind nur STEP und DIR.

Der Contoller, ist ein sogenannter Motion Controller für Fahr und Flug Simulation, der die Telemtrie Daten aus Applikationen in Bewegung umsetzt.
Controller 2 macht das derzeit schon mit 6 Motoren und einem MCP aber jedoch nur für die Step und Dir Signale, und es sind nur 60 Grad Bewegungen mit 50:1 Unterstützung.

Hier mal die Erläuterung welche Funktion die einzelnen Motoren haben:

Die Motoren 1-4 sind (heave) linear actuatoren mit 100-200mm Hub die direkt über 1605 spindeln angetrieben werden, d.h. pro Umdrehung 5mm der Motor kann zwar 3000 RPM ist aber auf 1500 RPM begrenzt.

Motoren 5-6 sind (traction loss) linear actuatoren mit 300mm Hub die direkt über 1605 spindeln angetrieben werden.

Motor 7 ist (surge) linear actuator mit 400mm Hub wobei dies als ref. Position die 200mm hat um dann jeweils 195mn in beide Richtungen zu verfahren.

Motor 8 ist (seatbelt tensioner) der max. Eine 180 Grad rotations Bewegung macht mit einer 2:1 Untersetzung.

nein das lese ich nicht raus. Ob du mit SS oder mit Adressen umschaltest wird sich nicht viel nehmen. Außer dass das Aktivieren (umschalten) wohl noch mehr zeit braucht. Die meisten libs verwenden dazu digitalWrite. Da ist eine andere Adresse vermutlich schneller.

Die telemetrie Daten werden, ja über das serielle Interface (115200 baud) als Telegram übergeben.

MCP23S17 ist schneller als MCP23017, das kann ich bestätigen. Wobei ich die maximale Geschwindigkeit von I²C beim ESP32 nicht einstellen konnte.

Das sehe ich auch so.

Eigentlich nur STEP, denn DIR wird ja nicht mitendrin umgeschaltet.

Mir fehlt eine Verbindung von INTA von MCP23S17_2 bis MCP23S17_4 mit dem ESP32, um Eingänge nur bei Bedarf abfragen zu müssen. Ein Eingang vom ESP32 reicht, wenn man INTA auf open drain setzt. Siehe setInterruptOD(). Ob man den Eingang dann periodisch abfragt oder per Interrupt auswertet, kann man dann beim Programmieren entscheiden.

Das heißt ich müsste jeden INTa dann auf einen einzelnen Pin am Esp32 anlegen. Aktuell sind alle MCP's aktiv oder habe ich einen Denkfehler gemacht,
beim Schaltungsentwurf.

Keinen Fehler. Aber wenn Du INTx nicht mit dem ESP32 verbindest, mußt Du die Eingänge ständig abfragen (Polling), was unnötig Zeit kostet.

Wenn ich es richtig erkennen kann, haben nur MCP23S17_2 bis MCP23S17_4 Eingänge. Du kannst aber auch INTx von MCP23S17_1 mit dem ESP32 verbinden, aber nicht nutzen. Man weiß ja nie :slightly_smiling_face:

  • 4 MCP * 2 INTx/MCP = 8 Pins am MCP maximal
    oder
  • je MCP ein ESP-Pin (mirror) = 4 Pins
    oder
  • je MCP mit Eingängen ein ESP-Pin (mirror) = 3 Pins
    oder
  • aber auch alle INTx von allen MCPs an einen ESP-Pin anschließen, wenn Du "mirror" und "open drain" verwendest.

Bezogen auf 6_kanal-Controller.zip:

motorStepDirValue = BIT_CLEAR(motorStepDirValue,dirPins[i]);
...
motorStepDirValue = BIT_SET(motorStepDirValue,dirPins[i]);

Das mag mein Kompiler nicht.


Da hat wohl jemand static und const verwechselt, daher richtig:

//constants for platform positions
const float theta_r = 10;
const float theta_s[6] = {150, -90, 30, 150, -90, 30};
const float theta_p = 30;
const float RD = 15.75;
const float PD = 16;
const float ServoArmLengthL1 = 7.25;
const float ConnectingArmLengthL2 = 28.5;
const float platformHeight = 25.5170749;

Für diese Bibliotheken kann ich im Programm keine Verwendung finden:

#include <Wire.h>
#include <EEPROM.h>
#include <cstring>

Danke für die ersten Fehlerbereinigungen am Controller 6 Kanal, werde es abändern und dann noch einmal kompilieren. Komme aber erst später dazu

Hallo,

ich bekomme beim kompilieren keinen Fehler, habe die Anmerkungen in der helper.h eingebaut. Hier der aktualisierte Sketch als ZIP

6_kanal-Controller.zip (56,6 KB)

Hier noch ein kleiner,
PCB-Debugger Skecth wegen des
motorStepDirValue = BIT_CLEAR(motorStepDirValue,dirPins[i]);
...
motorStepDirValue = BIT_SET(motorStepDirValue,dirPins[i]);

der dein Kompiler nicht mag.

PCB_Debugger.zip (7,4 KB)

Nutzt Du diese Voreinstellung?

grafik

Bei mir mit IDE 1.8.19:

F:\Arduino\ESP32\PCB_Debugger\PCB_Debugger.ino: In function 'void loop()':
PCB_Debugger:44:71: error: operation on 'motorStepDirValue' may be undefined [-Werror=sequence-point]
             motorStepDirValue = BIT_SET(motorStepDirValue,stepPins[i]);
                                                                       ^
PCB_Debugger:45:70: error: operation on 'motorStepDirValue' may be undefined [-Werror=sequence-point]
             motorStepDirValue = BIT_SET(motorStepDirValue,dirPins[i]);
                                                                      ^
cc1plus.exe: some warnings being treated as errors
exit status 1
operation on 'motorStepDirValue' may be undefined [-Werror=sequence-point]

Folgerichtig dann auch

F:\Arduino\ESP32\PCB_Debugger\helpers.cpp: In function 'float getAlpha(int, volatile float*)':
F:\Arduino\ESP32\PCB_Debugger\helpers.cpp:40:11: warning: unused variable 'alpha' [-Wunused-variable]
     float alpha[6] = {0,0,0, 0,0,0};
           ^
F:\Arduino\ESP32\PCB_Debugger\helpers.cpp: In function 'float rateLimit(float, float)':
F:\Arduino\ESP32\PCB_Debugger\helpers.cpp:94:10: warning: 'output' may be used uninitialized in this function [-Wmaybe-uninitialized]
   return output;
          ^
In file included from F:\Arduino\ESP32\PCB_Debugger\helpers.cpp:1:0:
F:\Arduino\ESP32\PCB_Debugger\helpers.h: At global scope:
F:\Arduino\ESP32\PCB_Debugger\helpers.h:23:14: warning: 'servoPulseMultiplierPerRadian' defined but not used [-Wunused-variable]
 static float servoPulseMultiplierPerRadian =  800/(pi/4);
              ^
F:\Arduino\ESP32\PCB_Debugger\PCB_Debugger.ino:675:38: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
 inline const char * const BoolToString(bool b)
                                      ^
F:\Arduino\ESP32\PCB_Debugger\PCB_Debugger.ino: In function 'void handleStepDirection()':
PCB_Debugger:494:73: error: operation on 'motorStepDirValue' may be undefined [-Werror=sequence-point]
             motorStepDirValue = BIT_CLEAR(motorStepDirValue,stepPins[i]);
                                                                         ^
PCB_Debugger:495:75: error: operation on 'motorStepDirValue2' may be undefined [-Werror=sequence-point]
             motorStepDirValue2 = BIT_CLEAR(motorStepDirValue2,stepPins[i]);
                                                                           ^
PCB_Debugger:514:77: error: operation on 'motorStepDirValue' may be undefined [-Werror=sequence-point]
                  motorStepDirValue = BIT_CLEAR(motorStepDirValue,dirPins[i]);
                                                                             ^
PCB_Debugger:515:79: error: operation on 'motorStepDirValue2' may be undefined [-Werror=sequence-point]
                  motorStepDirValue2 = BIT_CLEAR(motorStepDirValue2,dirPins[i]);
                                                                               ^
PCB_Debugger:519:74: error: operation on 'motorStepDirValue' may be undefined [-Werror=sequence-point]
                 motorStepDirValue = BIT_SET(motorStepDirValue,dirPins[i]);
                                                                          ^
PCB_Debugger:520:76: error: operation on 'motorStepDirValue2' may be undefined [-Werror=sequence-point]
                 motorStepDirValue2 = BIT_SET(motorStepDirValue2,dirPins[i]);
                                                                            ^
PCB_Debugger:530:79: error: operation on 'motorStepDirValue2' may be undefined [-Werror=sequence-point]
                   motorStepDirValue2 = BIT_SET(motorStepDirValue2,stepPins[i]);
                                                                               ^
PCB_Debugger:535:79: error: operation on 'motorStepDirValue2' may be undefined [-Werror=sequence-point]
                   motorStepDirValue2 = BIT_SET(motorStepDirValue2,stepPins[i]);
                                                                               ^
F:\Arduino\ESP32\PCB_Debugger\PCB_Debugger.ino: In function 'void checkEStop()':
F:\Arduino\ESP32\PCB_Debugger\PCB_Debugger.ino:600:7: warning: unused variable 'value' [-Wunused-variable]
   int value = debouncedEStop.read();
       ^
F:\Arduino\ESP32\PCB_Debugger\PCB_Debugger.ino: At global scope:
F:\Arduino\ESP32\PCB_Debugger\PCB_Debugger.ino:675:46: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
 inline const char * const BoolToString(bool b)
                                              ^
cc1plus.exe: some warnings being treated as errors
exit status 1
operation on 'motorStepDirValue' may be undefined [-Werror=sequence-point]

Zwei Gleichheitszeichen sind wohl etwas viel:

motorStepDirValue = ((motorStepDirValue) |= (1ULL<<(dirPins[i])));

Genügt nicht:

BIT_SET(motorStepDirValue,dirPins[i]);

Ich habe die 1.8.57.0 ide aus dem Windows store
Kompiler Warnungen Standard

Was ist das?
Aktuell ist 1.8.19