Arduino Mega und CAN-BUS Shield Nachricht senden bzw empfangen

Cool danke, werde es zum testen erst mal mit der message_rx Funktion probieren. Werde mir aber auch mal die Libary von Watterott anschauen und gegebenenfalls diese dann auch benutzen. Halte euch dann auf dem laufenden ;)

Techniker-KPK: Oder hat zufällig jemand eine Liste mit allen Befehlen ...

Bei der Bibliothek von Watterott findest Du die Methoden in MCP2515.h gelistet. Verwenden kannst Du die hinter public. Da stehen aber auch andere Informationen wie die möglichen Baudraten.

Was die Bibliothek wirklich treibt, findest Du in MCP2515.cpp aufgeführt. Auch wenn man da nicht alles versteht, sind manchmal erhellende Kommentare zu finden.

Hallöchen alle miteinander. Gestern war es nun soweit und ich habe es geschafft, eine Nachricht über den CAN-Bus zu verschicken.

https://www.magentacloud.de/lnk/vNyzLeI9#file

Links im Bild das bekannte Arduino Programm mit dem Sendebefehl im unteren Bereich

"CAN.sendMsgBuf(0x00, 0, 8, stmp);"

und direkt oben drüber die Hex-Nachricht welche verschickt werden soll

"0x27, 3, 0x91, 5, 4, 3, 6, 7"

Rechts im Bild ist ein Programm zu sehen, mit dem man in Verbindung eines CAN zu USB Adapters, diese Nachrichten empfangen kann. So auch rechts unten im Bild zu sehen :)

Verwendet habe ich jetzt diese Library von Seeed https://github.com/Seeed-Studio/CAN_BUS_Shield

Ich bedanke mich nochmal bei allen für eure tatkräftige Unterstützung. Echt ein klasse Forum ;)

Grüßle

Servus,

ich hab mal wieder eine kleine Frage :D

Und zwar sind wir mittlerweile an unsere Z-Achse angekommen, die über einen Linearantrieb mit einen Schrittmotor realisiert wird. Der Motor ist ein IGUS MOT-AN-S-060-005-042-L-A-AAAA der mit einer Spannung von 24V und einem Strom von 2A arbeitet. Für das Ansteuerung haben wir eine Ramps 1.4. Meine Frage ist jetzt, ob ich ausreicht, wenn ich an der Ramps nur die 5A Versorgung anschließe oder ob auch zwingend die 11A Versorgung angeschlossen werden muss. Bin mir nämlich nicht ganz sicher, da ich ja nur 2A brauche.

Vielleicht weis ja jemand was :)

Und dann wäre da noch die genaue Anteuerung der Ramps. Im Internet finde ich immer nur Anleitungen zu kompletten 3D-Druckern und das in Zusammenhang mit der Marlin Firmware. Ich bräuchte das ganze allerdings nur für einen einzigen Schrittmotor. Hat von euch jemand dazu eine passende Libary?

Vielen Dank schon mal ;)

Grüße Daniel

Technische Daten des Motors:

Nennspannung 24-48 VDC Nennstrom 1,8 A Widerstand/Phase 1,75 Ω

würde ich so interpretieren:

Spannung am Treiber 24-48 VDC Nennspannung 3,15 VDC Nennstrom 1,8 A Widerstand/Phase 1,75 Ω

Spannungsversorgung bezogen auf einen Motor: 24 VDC 2,6 A (siehe #28).

Welchen Treiber nutzt Du?

Genau, deswegen eben die Frage ob auch eben nur die 5A Versorgung reicht.

Es handelt sich um einen 4988ET Reicht das als Treiberinfo?

Grüße Daniel

Techniker-KPK: Es handelt sich um einen 4988ET

Einigen wir uns auf A4988, ok.

Techniker-KPK: Ich bräuchte das ganze allerdings nur für einen einzigen Schrittmotor. Hat von euch jemand dazu eine passende Libary?

A4988 (ich nutze DRV8825) steuere ich mit AccelStepper als Bibliothek (AccelStepper::DRIVER) an.

Hat die "5A Versorgung" auch eine Spannung? Ich finde in diesem Thema keinerlei Angaben dazu.

Also laut verschiedener Foren (genau Angaben beim Hersteller findet man leider nicht), kann unterschiedliche Spannung angelegt werden. Bei 12V kann man den Arduino gleich mitversorgen, ab 12V (was bei mir auch nötig wäre, da meine Stepper 24V brauchen) muss der Arduino extern betrieben werden und die Versorgungspins müssen unterbrochen werden (weis ich leider auch noch nicht genau wo :D). Also auf jedenfll benötige ich eine Spannung von 24V und 2A. So müsste ich doch auch einfach den 5A-Kreis von der Ramp ansteuern oder? Der 11A-Kreis ist doch nämlich nur für Heizplatten für einen 3D-Drucker oder irre ich mich da?

Die 1,8A des Motors sind pro Wicklung bezogen; Ein Schrittmotor hat 2 Wicklungen. Der A4988 ist ein Stromtreiber der in Summe max sqr(2) an Strom an den Motor (diesmal beide Wicklungen berechnet) gibt. Darum bei 1,8A eingestellten Strom brauchst Du mindestens ein 2,6A Netzteil.

Grüße Uwe

Ich habe ein Netzteil das als Output 24V und 6,2A ausgibt.

Techniker-KPK: Ich habe ein Netzteil das als Output 24V und 6,2A ausgibt.

Paßt, dann wie in dieser Beschreibung anschließen.

Super, vielen herzlichen Dank. Dann werd ich mich mal an die Arbeit machen ;)

Hi,

Ich habe can bus shield von seeed v1.2 und arduino uno. Ich habe die beiden so pin angeschlossen: Can arduino 9 10 11 11 12 12 13 13 Gnd gnd Vin Vin

Mit library von seeed-studio beispiel send kommt immer fehler can init fail. Wie haste das problem gelöst? Kann jemand mir doch helfen? Außerdem ist Strom über USB an Laptop angeschlossen.

https://www.arduino.cc/en/Main/arduinoBoardUno http://wiki.seeed.cc/CAN-BUS_Shield_V1.2/ https://github.com/Seeed-Studio/CAN_BUS_Shield

Einen wunderschönen Freitag Mittag :)

ich habe gedacht ich melde mich mal wieder und stelle eine kleine Frage an euch ;)

Aber davor gibt es mal ein kleines Bild von unserem Projekt ;)

|281x500

Aber jetzt zu meiner Frage.

Und zwar benutzen wir ein Pololu A4988 Treiber für unseren Schrittmotor der Z-Achse. Ist es möglich den Step-Eingang des Treibers mit einem PWM-Ausgang des Arduinos zu verwenden? Und wenn ja, wie genau kann ich den PWM-Ausgang programmieren? Also was für Einstellungen muss ich unternehmen?

Viele Grüße

Daniel

Techniker-KPK:
Ist es möglich den Step-Eingang des Treibers mit einem PWM-Ausgang des Arduinos zu verwenden?

Ein PWM-Ausgang erzeugt ein Rechtecksignal, das der Step-Eingang interpretieren kann. So gesehen funktioniert das. Allerdings hast Du bei analogWrite keine unmittelbare Kontrolle über die Anzahl der Schritte und die Frequenz ist auch festgelegt. Einen Sinn kann ich darin nicht entdecken.

Wenn Du den Timer direkt parametrierst, könnte was draus werden, nur würde ich das dann nicht mehr als PWM bezeichnen.

Oder hast Du eine andere Idee, auf die ich nicht komme?

Das eigentliche Problem ist, dass wenn ich es über einen normalen Ausgang mache, die Zykluszeit des Arduinos zu groß mit meinem Programm wird, dass der Motor nicht schnell genug getaktet werden kann. Normalerweise sind PWM-Ausgänge von der Zykluszeit unabhängig. Deswegen wollte ich es eben über den PWM machen, anstatt über einen normalen Output, den ich eben ein- und ausschalte.

Drei Achsen sollte ein Mega2560 aber ansteuern können. Beinhaltet der Sketch möglicherweise Blockaden?

Dürfte er eigentlich nicht haben. Vielleicht findest du ja was. Ist halt noch nicht das fertige Programm

#include <mcp_can.h>
#include <SPI.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int SPI_CS_PIN = 53;
const int buttonRight = 38;   //Taster rechts
const int buttonLeft = 39;    //Taster links
const int buttonUp = 22;      //Taster hoch
const int buttonDown = 23;    //Taster runter
const int buttonZup = 24;     //Taster Z-Achse hochfahren
const int buttonZdown = 25;   //Taster Z-Achse herunterfahren
const int buttonSlow = 26;    //Taster langsames Verfahren
const int buttonSave = 27;    //Taster Wert übergeben
const int buttonAM = 28;      //Taster Auswahl Manuell/Automatik
const int buttonRef = 37;     //Taster Auswahl Referenzfahrt
const int buttonX1 = 29;      //Endschalter X-Achse vorne
const int buttonX2 = 30;      //Endschalter X-Achse hinten
const int buttonY1 = 32;      //Endschalter Y-Achse links
const int buttonY2 = 31;      //Endschalter Y-Achse rechts
const int buttonZ1 = 33;      //Endschalter Z-Achse oben
const int buttonZ2 = 34;      //Endschalter Z-Achse unten
const int buttonZE1 = 35;     //Endschalter der Druckstärke, Ebene 1 oben
const int buttonZE2 = 36;     //Endschalter der Druckstärke, Ebene 2 unten
const int stepPin = 42; 
const int dirPin = 43; 
int interrupcion1 = 4;
int interrupcion2 = 5;


MCP_CAN CAN(SPI_CS_PIN); 

//Motorbefehle CAN-Bus
unsigned char rechts[7] = {01, 00, 00, 00, 00, 01, 0xf4};
unsigned char links[7] = {02, 00, 00, 00, 00, 01, 0xf4};
unsigned char runter[7] = {01, 00, 00, 00, 00, 01, 0xf4};
unsigned char hoch[7] = {02, 00, 00, 00, 00, 01, 0xf4};
unsigned char rechts_slow[7] = {01, 00, 00, 00, 00, 00, 0xfa};
unsigned char links_slow[7] = {02, 00, 00, 00, 00, 00, 0xfa};
unsigned char runter_slow[7] = {01, 00, 00, 00, 00, 00, 0xfa};
unsigned char hoch_slow[7] = {02, 00, 00, 00, 00, 00, 0xfa};
unsigned char halt[7] = {03, 00, 00, 00, 00, 00, 00};
unsigned char microsteps[7] = {05, 0x8c, 00, 00, 00, 00, 0x06};
unsigned char microsteps_slow[7] = {05, 0x8c, 00, 00, 00, 00, 0x08};
unsigned char akt_position[7] = {06, 01, 00, 00, 00, 00, 00};
unsigned char len = 0;
unsigned char buf[7];

int verticalstop = 0;
int horizontalstop = 0; 

int end_y=0;
int end_x=0;
int auswahl;
int referenz_abfrage=0;
 
void setup() 
{ 
  attachInterrupt(interrupcion1, funcionInterrupcion, LOW);
  attachInterrupt(interrupcion2, funcionInterrupcion, LOW);
  pinMode(buttonRight, INPUT);
  pinMode(buttonLeft, INPUT);
  pinMode(buttonUp, INPUT);
  pinMode(buttonDown, INPUT);
  pinMode(buttonZup, INPUT);
  pinMode(buttonZdown, INPUT);
  pinMode(buttonSlow, INPUT);
  pinMode(buttonSave, INPUT);
  pinMode(buttonAM, INPUT);
  pinMode(buttonRef, INPUT);
  pinMode(buttonX1, INPUT);
  pinMode(buttonX2, INPUT);
  pinMode(buttonY1, INPUT);
  pinMode(buttonY2, INPUT);
  pinMode(buttonZ1, INPUT);
  pinMode(buttonZ2, INPUT);
  pinMode(buttonZE1, INPUT);
  pinMode(buttonZE2, INPUT);
  pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  
  Serial.begin(115200);  
  lcd.begin(20,4);                                               // initialize the lcd for 20 chars 4 lines

  while (CAN_OK != CAN.begin(CAN_1000KBPS))                      // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println(" Init CAN BUS Shield again");
        delay(100);
    }
    Serial.println("CAN BUS Shield init ok!");
}

void loop() 
{
  while(1){
  if(digitalRead(buttonRef)==HIGH & digitalRead(buttonAM)==LOW)   //Auswahl Referenzfahrt
  {
    auswahl=1;
  }
  if(digitalRead(buttonRef)==LOW & digitalRead(buttonAM)==HIGH)   //Auswahl Manuell
  {
    auswahl=2;
  }
  if(digitalRead(buttonRef)==LOW & digitalRead(buttonAM)==LOW)    //Auswahl Automatik
  {
    auswahl=3;
  }

  case(auswahl)
  {
    case 1: 
    {
      referenz(); 
      break;
    }
    case 2:
    {
      if(referenz_abfrage==0)
      {
        lcd_referenzfahrt();    
      }
      if(referenz_abfrage==1)
      {
        manuell();
      }
      break;
    }
    case 3:
    {
      if(referenz_abfrage==0)
      {
        lcd_referenzfahrt();    
      }
      if(referenz_abfrage==1)
      {
        automatik();
      }
      break;
    }
  }
  manuell();
  }
}

void referenz(void)
{
  int abfrage_hinten=0;
  int abfrage_vorne=0;
  int abfrage_links=0;
  int abfrage_rechts=0;
  init_motor_slow();
  
  referenz_abfrage=1;  
}

hier ist der Rest :wink:

void manuell(void)
{
  if(digitalRead(buttonSlow)==HIGH)                             //Wenn die Taste für langsames Fahren betätigt wird, so werden die Motoren mit einer feineren Microstep Auflösung bespielt
  {
    init_motor_slow();
  }
  else                                                          //Wenn die Taste für langsameres Fahren NICHT betätigt wird, so wird die Standard Auflösung auf die Motoren bespielt
  {
    init_motor();   
  }

  if(digitalRead(buttonY2)==LOW | digitalRead(buttonY1)==LOW)   //Wenn Y-Endschalter rechts oder Y-Endschalter links betätigt wird, so wird der Befehl "halt" an den Y-Motor geschickt
  {
    while(end_y==0)                                             //Schleife, dass der Befehl nur EINMAL geschickt wird 
    {
      CAN.sendMsgBuf(0x01, 0, 7, halt); 
      end_y++;
    }
  }
  
  if(digitalRead(buttonRight)==HIGH & digitalRead(buttonLeft)==LOW & digitalRead(buttonY2)==HIGH)    //Wenn Taster für Rechtsfahrt betätigt wird und der Y-Endschalter rechts NICHT betätigt ist, so fährt die Anlage nach rechts 
  {
    if(digitalRead(buttonSlow)==HIGH)                                 //Wenn Taste "langsam" betätigt wird, so wird der Motor mit einer geringeren Drehzahl bespielt
    {
      CAN.sendMsgBuf(0x01, 0, 7, rechts_slow);
      verticalstop=1;                                                 //Variable die auf "1" gesetzt wird, um den Befehl zum "halten" beim loslassen ausführen zu können
      end_y=0;  
    }
    else                                                              //Motor fährt mit normaler Geschwindigkeit
    {
      CAN.sendMsgBuf(0x01, 0, 7, rechts);
      verticalstop=1;                                                 //Variable die auf "1" gesetzt wird, um den Befehl zum "halten" beim loslassen ausführen zu können
      end_y=0;
    } 
  }
  
  if(digitalRead(buttonLeft)==HIGH & digitalRead(buttonRight)==LOW & digitalRead(buttonY1)==HIGH)    //Wenn Taster für Linksfahrt betätigt wird und der Y-Endschalter links NICHT betätigt ist, so fährt die Anlage nach links
  {
    if(digitalRead(buttonSlow)==HIGH)                                //Wenn Taste "langsam" betätigt wird, so wird der Motor mit einer geringeren Drehzahl bespielt
    {
      CAN.sendMsgBuf(0x01, 0, 7, links_slow);
      verticalstop=1;                                                //Variable die auf "1" gesetzt wird, um den Befehl zum "halten" beim loslassen ausführen zu können
      end_y=0;  
    }
    else                                                             //Motor fährt mit normaler Geschwindigkeit              
    {
      CAN.sendMsgBuf(0x01, 0, 7, links);
      verticalstop=1;                                                //Variable die auf "1" gesetzt wird, um den Befehl zum "halten" beim loslassen ausführen zu können
      end_y=0;
    } 
  }

  if(((digitalRead(buttonRight)==LOW & digitalRead(buttonLeft)==LOW) | (digitalRead(buttonRight)==HIGH & digitalRead(buttonLeft)==HIGH)) & verticalstop==1 )   //Wenn keiner der Taster für "links" und "rechts" betätigt ist und die 
  {                                                                                       //Variable verticalstop=1 ist, oder beide Taster gleichzeitig gedrückt werden, so wird der Befehl zum stoppen gesendet
    CAN.sendMsgBuf(0x01, 0, 7, halt); 
    verticalstop=0;                                                  //Variable wird auf "0" zurückgesetzt
    positionsabfrage_X();
    positionsabfrage_Y();
  }

  if(digitalRead(buttonX2)==LOW | digitalRead(buttonX1)==LOW)        //Wenn Y-Endschalter rechts oder Y-Endschalter links betätigt wird, so wird der Befehl "halt" an den Y-Motor geschickt
  {
    while(end_x==0)                                                  //Schleife, dass der Befehl nur EINMAL geschickt wird 
    {
      CAN.sendMsgBuf(0x02, 0, 7, halt); 
      end_x++;
    }
  }

  if(digitalRead(buttonDown)==HIGH & digitalRead(buttonUp)==LOW & digitalRead(buttonX2)==HIGH)    //Wenn Taster für Runterfahrt betätigt wird und der X-Endschalter hinten NICHT betätigt ist, so fährt die Anlage nach unten   
  {
    if(digitalRead(buttonSlow)==HIGH)                                
    {
      CAN.sendMsgBuf(0x02, 0, 7, runter_slow);
      horizontalstop=1;                                               
      end_x=0;  
    }
    else                                                            
    {
      CAN.sendMsgBuf(0x02, 0, 7, runter);
      horizontalstop=1;                                              
      end_x=0;
    } 
  }
  
  if(digitalRead(buttonUp)==HIGH & digitalRead(buttonDown)==LOW & digitalRead(buttonX1)==HIGH)      
  {
    if(digitalRead(buttonSlow)==HIGH)                               
    {
      CAN.sendMsgBuf(0x02, 0, 7, hoch_slow);
      horizontalstop=1;                                               
      end_x=0;  
    }
    else                                                             
    {
      CAN.sendMsgBuf(0x02, 0, 7, hoch);
      horizontalstop=1;                                               
      end_x=0;
    } 
  }

  if(((digitalRead(buttonUp)==LOW & digitalRead(buttonDown)==LOW) | (digitalRead(buttonUp)==HIGH & digitalRead(buttonDown)==HIGH)) & horizontalstop==1)   
  {                                                                                   
    CAN.sendMsgBuf(0x02, 0, 7, halt); 
    horizontalstop=0;                                                 
    positionsabfrage_X();
    positionsabfrage_Y();
  }  

  if(digitalRead(buttonZup)==HIGH & digitalRead(buttonZ1)==HIGH)
  {
    stepmotor_up();
  }
   if(digitalRead(buttonZdown)==HIGH & digitalRead(buttonZ2)==HIGH & digitalRead(buttonZE1)==HIGH)
   {
      stepmotor_down();
   }
}

void funcionInterrupcion()
{
  Serial.println("E-Stop");
  lcd_notaus();
}

void stepmotor_up(void)
{
  digitalWrite(dirPin,HIGH); // Enables the motor to move in a particular direction
  // Makes 200 pulses for making one full cycle rotation
  
  digitalWrite(stepPin,HIGH); 
  delayMicroseconds(200); 
  digitalWrite(stepPin,LOW); 
  delayMicroseconds(200); 
  Serial.println("hoch");
}

void stepmotor_down(void)
{
  digitalWrite(dirPin,LOW); //Changes the rotations direction
  // Makes 400 pulses for making two full cycle rotation
  
  digitalWrite(stepPin,HIGH);
  delayMicroseconds(200);
  digitalWrite(stepPin,LOW);
  delayMicroseconds(200); 
  Serial.println("runter"); 
}

void init_motor(void)                                 //Initialisierung mit normaler Microstep Auflösung
{
  CAN.sendMsgBuf(0x01, 0, 7, microsteps);  
  CAN.sendMsgBuf(0x02, 0, 7, microsteps);
}

void init_motor_slow(void)                            //Initialisierung mit feineren Microstep Auflösung
{
  CAN.sendMsgBuf(0x01, 0, 7, microsteps_slow);  
  CAN.sendMsgBuf(0x02, 0, 7, microsteps_slow);  
}

void lcd_referenzfahrt(void)
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Bitte zuerst");
  lcd.setCursor(0,1);
  lcd.print("Referenzfahrt durchführen!");
}

void positionsabfrage_X(void)
{
  for(int b=0; b<7;b++)
  {
    buf[b]=0;
  }
  CAN.sendMsgBuf(0x01, 0, 7, akt_position);
  if(CAN_MSGAVAIL == CAN.checkReceive())
  {
    CAN.readMsgBuf(&len, buf);
  }
  lcd.clear();
  lcd.setCursor ( 0, 0);
  lcd.print("X-Position: "); 
  int arr=3;
  for(int column = 0; column<8; column=column+2)
  {
    lcd.setCursor(column, 1);
    lcd.print(buf[arr], HEX);
    arr++;
  }   
}

void positionsabfrage_Y(void)
{
  for(int b=0; b<7;b++)
  {
    buf[b]=0;
  }
  CAN.sendMsgBuf(0x02, 0, 7, akt_position);
  if(CAN_MSGAVAIL == CAN.checkReceive())
  {
    CAN.readMsgBuf(&len, buf);
  }
  lcd.setCursor ( 0, 2);
  lcd.print("Y-Position: "); 
  int arr=3;
  for(int column = 0; column<8; column=column+2)
  {
    lcd.setCursor(column, 3);
    lcd.print(buf[arr], HEX);
    arr++;
  }   
}

void anzeige(void)
{ 
  lcd.clear();
  lcd.setCursor ( 0, 0);
  lcd.print("X-Position: ");  
  lcd.setCursor ( 0, 1 );        // go to the next line
  lcd.print ("");     
  lcd.setCursor ( 0, 2 );        // go to the next line
  lcd.print ("Tastenaktuator");   
  lcd.setCursor ( 0, 3 );        // go to the next line
  lcd.print ("");  
}

void anzeige2(void)
{ 
  lcd.clear();
  lcd.setCursor ( 2, 0);
  lcd.print("KPK Engineering");  
  lcd.setCursor ( 3, 1 );        // go to the next line
  lcd.print ("");     
  lcd.setCursor ( 2, 2 );        // go to the next line
  lcd.print ("Technikerprojekt");   
  lcd.setCursor ( 3, 3 );        // go to the next line
  lcd.print ("");  
}

Techniker-KPK: Vielleicht findest du ja was.

Ein paar Eindrücke: - while(1) in loop finde ich befremdlich. Ob sich daraus Probleme ergeben, weiß ich nicht. - Inwieweit CAN.sendMsgBuf Zeit raubt, kann ich nicht einschätzen, wäre aber möglich. - Serial.println("hoch"); und Serial.println("runter"); benötigen Zeit, sollte nicht bei jedem Schritt ausgegeben werden. - Auch delayMicroseconds(200); blockiert in der Summe von vielen Schritten. Schonmal mit Micros() probiert? - lcd.clear(); ist blockierend, hat aber wohl keinen Einfluß. Fasse meine Anmerkungen bitte als Anregung zu eigenen Überlegungen auf :)