Versteckte Pins am Adafruit Motor Shield v2 und der PCA9685 (Erfahrungsbericht)

Hallo!

Versteckte Funktionen oder wie man das Shield aufpeppt. :slight_smile: Ein paar Ideen für die Community.
Das Adafruit Motor Shield v2 und der PCA9685 (Erfahrungsbericht).

Wer von euch das Adafruit Motor Shield v2 hat, dem ist vielleicht aufgefallen das rechts auf dem Lochraster 4 Pins mit (# gekenzeichnet) sind. Falls ihr diese Pins verwenden wollt müsst ihr nur den Code (weiter unten) einfügen.

Das Breakout des PCA9685 (Datenblatt) kann auf 16 Kanälen ein 12Bit PWM Signal generieren. Er wird über den I2C Bus angesteuert und arbeitet in einem Frequenzbereich von 25Hz – 1400Hz. Für einen Servomotor braucht man 50Hz, für LEDs sind 1000Hz geeignet. Dokumentation von Adafruit

Das Adafruit Motor Shield v2, kann 4 DC-Motoren oder 2 Schrittmotoren ansteuern und es ist mit Stackable Headers stapelbar.
Als H-Brücke werden 2 TB6612 (Datenblatt) verwendet die über den PCA9685 gesteuert werden.

Da bleiben 4 Pins übrig, die man auch verwenden kann. Sie befinden sich rechts auf dem Lochraster und sind mit #0, #1, #14 und #15 beschriftet. Dies geht auch relativ einfach, im Beispiel Sketch ‘DCMotorTest’, der Library wird das Objekt AFMS genannt. Behält man dies bei, reicht folgender Befehl:

AFMS.setPWM(PCApin, pulslenth); // pulslenth = 0-4096
/* Beispiele: */
AFMS.begin(1000)  // Startet/Reset den PCA9685 mit 1000 Hz 
AFMS.setPWM(0, 2048); // Erzeugt einen Duty Cycle von 50% auf Pin 0 am PCA9685
analog.write(arduinoPin, 128)  // // Erzeugt einen Duty Cycle von 50% auf einem Arduino PWM Pin

Um einen Servo Motor anzusteuern, müsste man die Frequenz auf 50Hz drosseln. Da kann man die Motoren leider vergessen. Man hört ‚fast‘, wie der Motor Ein/Ausgeschaltet wird. Ich kann nicht ständig die Frequenz ändern, aber ich kann einen zweiten PCA9685 (den es auch als Shield gibt) Stapeln und die beiden getrennt voneinander ansprechen.

Auch wenn Servo Motoren toll wären, gibt noch andere Anwendungsmöglichkeiten, wie das Ein/Ausschalten diverses Bauelemente, das Dimmen von LEDs oder das steuern eines Motors über einen MOSFET*1. Theoretisch kann man das Shield auch mit einer H-Brücke für einen weiteren Schrittmotor erweitern. Hier sollte die Frequenz des PCA9685 nicht unter 1kHz eingestellt werden.

Es gibt theoretisch auch die Möglichkeit noch einmal 4 DC-Motoren anzuschließen. Ein IC wie der CD4093 kann ein PWM Signal für einen L293D ‘aufbereiten’ (siehe angehängten Schaltplan). Der Schaltplan funktioniert am Arduino und auch mit dem PCA9685, je mit 2 Motoren getestet.

Auf meinem Protobereich habe ich eine Anschlussmöglichkeit für einen HC-06 gelötet. Auch ein Spannungsteiler (5V → 3,3V; 5,4kΩ/10kΩ) ist zwischen dem TX Pin am Arduino und dem Rx Pin am HC-06 fest verbaut (gelötet).

Da ich das Motor Shield auf einem ‚Roboter Auto‘ verwende, werde ich die 4 übrigen Pins für die LEDs verwenden. (das einzige Problem ist derzeit *1). Mich würde vor allem interessieren wieviel mA ein Pin verkraftet und wie ich diesen Modus ändern kann? (MOSFET: NPN, PNP oder direkt zur LED) Ich weiß… in dem Register des PCA9685 schreiben… aber wie funktioniert das genau, Code? (Ich werde es schon schaffen) aber vielleicht kann mir jemand dabei helfen, wie ich Überprüfen kann, welcher Modus aktiv ist? Mir ist schon klar, dass ich den Modus nicht am Motor Shield ändern kann aber auf den Breakout.

*1 Im Datenblatt des PCA9685 gibt es viele Möglichkeiten die es in der lib nicht gibt. Bestes Beispiel ist auf Seite 29 (unten). Ich habe zwar noch nicht nach anderen libs gesucht, am liebsten würde ich da selber etwas machen aber da reichen meine Kenntnisse leider noch nicht aus. Was nicht ist kann aber noch werden. :wink:

Außerdem wäre ich für Ideen, Hinweise oder konstruktive Kritik Dankbar.

lg dony
edit: Hab den Code angepasst. Schaut euch den Schaltplan an, damit lassen sich 2 DC-Motoren über 2 PWM Signale steuern.

Hallo nochmal,

Ich habe einen Sketch für den obigen Schaltplan mit dem CD4093 gefunden und etwas ‘hergerichtet’.

/* CD4093 ansprechen
 * analogWrite(pin, pwm_laenge);
 * < ------ | ------ >
 * 0   85  128  200  255
 * 
 * currentSpeed:
 * 0 = Vollgas Rückwärts
 * 100 = langsam Rückwärtsfahren
 * 127 = sehr sehr langsam Rückwärtsfahren
 * 128 = Stopp
 * 200 = schnell Vorwärtsfahren
 * 255 = Vollgas Vorwärts
 */
byte enablePin = 8;  // 
byte motorPin = 9;

uint8_t currentSpeed = 200;
bool directionM1 = true;  // 0 = rückwärts, 1 = Vorwärts

void setup() {
  Serial.begin(9600);
  Serial.println("Willkommen");
  pinMode(enablePin, OUTPUT);
  enableMotor();
}
void enableMotor() {
  //if(currentSpeed <= 128) { currentSpeed = 200; } // schnelles Vorwärts fahren 
  digitalWrite(enablePin, HIGH);
  analogWrite(motorPin, 128);
}
void disableMotor() {
  currentSpeed = 128;
  analogWrite(motorPin, 128);
  digitalWrite(enablePin, LOW);
}
void changeDir() {
  if(currentSpeed > 128) { // Vorwärtsfahren
    currentSpeed = map(currentSpeed, 255, 0, 0, 255);
  }
  else if(currentSpeed < 128) {  // Rückwärtsfahren
    currentSpeed = map(currentSpeed, 0, 255, 255, 0);
  }
  else {  //  Motor Stopp
    currentSpeed = 128;
  }
  directionM1 != directionM1; // ändere Richtung
  analogWrite(motorPin, currentSpeed);
}
void setMotorSpeed(uint8_t curSpeed) {
  analogWrite(motorPin, curSpeed);
}
void loop() {
  // Geschwindigkeit setzen
  // currentSpeed = 128 // 128 = Stopp, 80 = langsam Rückwärts, 200 = schnell Vorwärts, max. 255
  // analogWrite(motorPin, currentSpeed);

  Serial.print("Speed: ");
  Serial.println(currentSpeed);

  setMotorSpeed(currentSpeed);  // Geschwindikeit setzen (siehe CurrentSpeed Kommentar)
  delay(500);
  changeDir();  // Richtungswechsel
  delay(500);
}

Ich habe den Code kurz getestet, sollte auch funktionieren. Bevor ich die Schaltung nicht nochmal aufbaue, kann ich auch nicht zu 100% sicher gehen.

lg dony