Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[Inne] Ploter na bazie Arduino nano

30 Mar 2018 00:36 912 8
  • Poziom 4  
    Mam problem pozornie dużo jest tematów jak zrobić prosty ploter wykorzystując silniczki z napędów DVD .Są schematy jak zbudować to urządzenie przy pomocy Arduino nano i L93D . Wykonałem prototyp ,przetestowałem silniczki ale jak chce wykorzystać program gdzie jest biblioteka Stepper.h a nie ma biblioteki grblmain.h to program nie współdziała np. z Universal Gcode Sender. Rozumiem program gdzie jest wykorzystana biblioteka Stepper.h i mogę go dopasować do mojej płytki , tylko czym wtedy sterować ? Nie chciałbym kupować specjalnie Arduino UNO z dodatkami aby móc skorzystać bibliotek GRBL i na tym zakończyć. Czy ktoś już rozwiązał ten problem sterowania dla Arduino nano ?[/youtube]
  • Poziom 12  
    "The Arduino Nano is a compact board similar to the UNO.", czyli jeżeli program działa na UNO, to bez żadnych przeróbek powinien działać na Nano.
  • Poziom 4  
    Racja i stąd się bierze moja frustracja bo program
    Code:
    #include <Servo.h>
    
    #include <Stepper.h>

    #define LINE_BUFFER_LENGTH 512

    const int penZUp = 80;
    const int penZDown = 40;

    const int penServoPin = 2;

    const int stepsPerRevolution = 20;

    Servo penServo;

    //Stepper myStepperY(stepsPerRevolution, 2,3,4,5);
    //Stepper myStepperX(stepsPerRevolution, 8,9,10,11);
    Stepper myStepperY(stepsPerRevolution, 4,5,6,7);
    Stepper myStepperX(stepsPerRevolution, 8,9,10,11);

    struct point {
    float x;
    float y;
    float z;
    };

    struct point actuatorPos;

    float StepInc = 1;
    int StepDelay = 0;
    int LineDelay = 50;
    int penDelay = 50;

    float StepsPerMillimeterX = 6.0;
    float StepsPerMillimeterY = 6.0;

    float Xmin = 0;
    float Xmax = 40;
    float Ymin = 0;
    float Ymax = 40;
    float Zmin = 0;
    float Zmax = 1;

    float Xpos = Xmin;
    float Ypos = Ymin;
    float Zpos = Zmax;

    boolean verbose = false;

    void setup() {
    Serial.begin( 9600 );

    penServo.attach(penServoPin);
    penServo.write(penZUp);
    delay(200);

    myStepperX.setSpeed(250);
    myStepperY.setSpeed(250);

    Serial.println("Mini CNC Plotter alive and kicking!");
    Serial.print("X range is from ");
    Serial.print(Xmin);
    Serial.print(" to ");
    Serial.print(Xmax);
    Serial.println(" mm.");
    Serial.print("Y range is from ");
    Serial.print(Ymin);
    Serial.print(" to ");
    Serial.print(Ymax);
    Serial.println(" mm.");
    }

    void loop()
    {
    delay(200);
    char line[ LINE_BUFFER_LENGTH ];
    char c;
    int lineIndex;
    bool lineIsComment, lineSemiColon;

    lineIndex = 0;
    lineSemiColon = false;
    lineIsComment = false;

    while (1) {

    while ( Serial.available()>0 ) {
    c = Serial.read();
    if (( c == '\n') || (c == '\r') ) {
    if ( lineIndex > 0 ) {
    line[ lineIndex ] = '\0';
    if (verbose) {
    Serial.print( "Received : ");
    Serial.println( line );
    }
    processIncomingLine( line, lineIndex );
    lineIndex = 0;
    }
    else {

    }
    lineIsComment = false;
    lineSemiColon = false;
    Serial.println("ok");
    }
    else {
    if ( (lineIsComment) || (lineSemiColon) ) { // Throw away all comment characters
    if ( c == ')' ) lineIsComment = false; // End of comment. Resume line.
    }
    else {
    if ( c <= ' ' ) { // Throw away whitepace and control characters
    }
    else if ( c == '/' ) { // Block delete not supported. Ignore character.
    }
    else if ( c == '(' ) { // Enable comments flag and ignore all characters until ')' or EOL.
    lineIsComment = true;
    }
    else if ( c == ';' ) {
    lineSemiColon = true;
    }
    else if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) {
    Serial.println( "ERROR - lineBuffer overflow" );
    lineIsComment = false;
    lineSemiColon = false;
    }
    else if ( c >= 'a' && c <= 'z' ) { // Upcase lowercase
    line[ lineIndex++ ] = c-'a'+'A';
    }
    else {
    line[ lineIndex++ ] = c;
    }
    }
    }
    }
    }
    }

    void processIncomingLine( char* line, int charNB ) {
    int currentIndex = 0;
    char buffer[ 64 ]; // Hope that 64 is enough for 1 parameter
    struct point newPos;

    newPos.x = 0.0;
    newPos.y = 0.0;

    // Needs to interpret
    // G1 for moving
    // G4 P300 (wait 150ms)
    // G1 X60 Y30
    // G1 X30 Y50
    // M300 S30 (pen down)
    // M300 S50 (pen up)
    // Discard anything with a (
    // Discard any other command!

    while( currentIndex < charNB ) {
    switch ( line[ currentIndex++ ] ) { // Select command, if any
    case 'U':
    penUp();
    break;
    case 'D':
    penDown();
    break;
    case 'G':
    buffer[0] = line[ currentIndex++ ]; // /!\ Dirty - Only works with 2 digit commands
    // buffer[1] = line[ currentIndex++ ];
    // buffer[2] = '\0';
    buffer[1] = '\0';

    switch ( atoi( buffer ) ){ // Select G command
    case 0: // G00 & G01 - Movement or fast movement. Same here
    case 1:
    // /!\ Dirty - Suppose that X is before Y
    char* indexX = strchr( line+currentIndex, 'X' ); // Get X/Y position in the string (if any)
    char* indexY = strchr( line+currentIndex, 'Y' );
    if ( indexY <= 0 ) {
    newPos.x = atof( indexX + 1);
    newPos.y = actuatorPos.y;
    }
    else if ( indexX <= 0 ) {
    newPos.y = atof( indexY + 1);
    newPos.x = actuatorPos.x;
    }
    else {
    newPos.y = atof( indexY + 1);
    indexY = '\0';
    newPos.x = atof( indexX + 1);
    }
    drawLine(newPos.x, newPos.y );
    // Serial.println("ok");
    actuatorPos.x = newPos.x;
    actuatorPos.y = newPos.y;
    break;
    }
    break;
    case 'M':
    buffer[0] = line[ currentIndex++ ]; // /!\ Dirty - Only works with 3 digit commands
    buffer[1] = line[ currentIndex++ ];
    buffer[2] = line[ currentIndex++ ];
    buffer[3] = '\0';
    switch ( atoi( buffer ) ){
    case 300:
    {
    char* indexS = strchr( line+currentIndex, 'S' );
    float Spos = atof( indexS + 1);
    // Serial.println("ok");
    if (Spos == 30) {
    penDown();
    }
    if (Spos == 50) {
    penUp();
    }
    break;
    }
    case 114: // M114 - Repport position
    Serial.print( "Absolute position : X = " );
    Serial.print( actuatorPos.x );
    Serial.print( " - Y = " );
    Serial.println( actuatorPos.y );
    break;
    default:
    Serial.print( "Command not recognized : M");
    Serial.println( buffer );
    }
    }
    }



    }



    void drawLine(float x1, float y1) {

    if (verbose)
    {
    Serial.print("fx1, fy1: ");
    Serial.print(x1);
    Serial.print(",");
    Serial.print(y1);
    Serial.println("");
    }


    if (x1 >= Xmax) {
    x1 = Xmax;
    }
    if (x1 <= Xmin) {
    x1 = Xmin;
    }
    if (y1 >= Ymax) {
    y1 = Ymax;
    }
    if (y1 <= Ymin) {
    y1 = Ymin;
    }

    if (verbose)
    {
    Serial.print("Xpos, Ypos: ");
    Serial.print(Xpos);
    Serial.print(",");
    Serial.print(Ypos);
    Serial.println("");
    }

    if (verbose)
    {
    Serial.print("x1, y1: ");
    Serial.print(x1);
    Serial.print(",");
    Serial.print(y1);
    Serial.println("");
    }

    // Convert coordinates to steps
    x1 = (int)(x1*StepsPerMillimeterX);
    y1 = (int)(y1*StepsPerMillimeterY);
    float x0 = Xpos;
    float y0 = Ypos;

    // Let's find out the change for the coordinates
    long dx = abs(x1-x0);
    long dy = abs(y1-y0);
    int sx = x0<x1 ? StepInc : -StepInc;
    int sy = y0<y1 ? StepInc : -StepInc;

    long i;
    long over = 0;

    if (dx > dy) {
    for (i=0; i<dx; ++i) {
    myStepperX.step(sx);
    over+=dy;
    if (over>=dx) {
    over-=dx;
    myStepperY.step(sy);
    }
    delay(StepDelay);
    }
    }
    else {
    for (i=0; i<dy; ++i) {
    myStepperY.step(sy);
    over+=dx;
    if (over>=dy) {
    over-=dy;
    myStepperX.step(sx);
    }
    delay(StepDelay);
    }
    }

    if (verbose)
    {
    Serial.print("dx, dy:");
    Serial.print(dx);
    Serial.print(",");
    Serial.print(dy);
    Serial.println("");
    }

    if (verbose)
    {
    Serial.print("Going to (");
    Serial.print(x0);
    Serial.print(",");
    Serial.print(y0);
    Serial.println(")");
    }


    delay(LineDelay);

    Xpos = x1;
    Ypos = y1;
    }


    void penUp() {
    penServo.write(penZUp);
    delay(LineDelay);
    Zpos=Zmax;
    if (verbose) {
    Serial.println("Pen up!");
    }
    }
    void penDown() {
    penServo.write(penZDown);
    delay(LineDelay);
    Zpos=Zmin;
    if (verbose) {
    Serial.println("Pen down.");
    }
    }

    po wgraniu do Arduino nano i uruchomieniu np. GrblPanel pomimo wysyłania kodu przez program silniki nie są sterowane :(
  • Poziom 4  
    W końcu pojawiło się światełko w tunelu użyłem programu
    Code:


    /*
     Mini CNC Plotter firmware, based in TinyCNC https://github.com/MakerBlock/TinyCNC-Sketches
     Send GCODE to this Sketch using gctrl.pde https://github.com/damellis/gctrl
     Convert SVG to GCODE with MakerBot Unicorn plugin for Inkscape available here https://github.com/martymcguire/inkscape-unicorn
     
     More information about the Mini CNC Plotter here (german, sorry): http://www.makerblog.at/2015/02/projekt-mini-cnc-plotter-aus-alten-cddvd-laufwerken/


      */

    #include <Servo.h>
    #include <Stepper.h>

    #define LINE_BUFFER_LENGTH 512

    // Servo position for Up and Down
    const int penZUp = 80;
    const int penZDown = 40;

    // Servo on PWM pin 6
    const int penServoPin = 2;

    // Should be right for DVD steppers, but is not too important here
    const int stepsPerRevolution = 42;

    // create servo object to control a servo
    Servo penServo; 

    // Initialize steppers for X- and Y-axis using this Arduino pins for the L293D H-bridge
    Stepper myStepperY(stepsPerRevolution, 4,5,6,7);           
    Stepper myStepperX(stepsPerRevolution, 8,9,10,11); 

    /* Structures, global variables    */
    struct point {
      float x;
      float y;
      float z;
    };

    // Current position of plothead
    struct point actuatorPos;

    //  Drawing settings, should be OK
    float StepInc = 1;
    int StepDelay = 0;
    int LineDelay = 50;
    int penDelay = 50;

    // Motor steps to go 1 millimeter.
    // Use test sketch to go 100 steps. Measure the length of line.
    // Calculate steps per mm. Enter here.
    float StepsPerMillimeterX = 42.0;
    float StepsPerMillimeterY = 42.0;

    // Drawing robot limits, in mm
    // OK to start with. Could go up to 50 mm if calibrated well.
    float Xmin = 0;
    //float Xmax = 200;
    float Xmax = 40;
    float Ymin = 0;
    //float Ymax = 260;
    float Ymax = 26;
    float Zmin = 0;
    float Zmax = 1;

    float Xpos = Xmin;
    float Ypos = Ymin;
    float Zpos = Zmax;

    // Set to true to get debug output.
    boolean verbose = false;

    //  Needs to interpret
    //  G1 for moving
    //  G4 P300 (wait 150ms)
    //  M300 S30 (pen down)
    //  M300 S50 (pen up)
    //  Discard anything with a (
    //  Discard any other command!

    /**********************
     * void setup() - Initialisations
     ***********************/
    void setup() {
      //  Setup
      Serial.begin( 9600 );
     
      penServo.attach(penServoPin);
      penServo.write(penZUp);
      delay(200);

      // Decrease if necessary
      myStepperX.setSpeed(250);
      myStepperY.setSpeed(250); 

      //  Set & move to initial default position
      // TBD

      //  Notifications!!!
      Serial.println("Mini CNC Plotter alive and kicking!");
      Serial.print("X range is from ");
      Serial.print(Xmin);
      Serial.print(" to ");
      Serial.print(Xmax);
      Serial.println(" mm.");
      Serial.print("Y range is from ");
      Serial.print(Ymin);
      Serial.print(" to ");
      Serial.print(Ymax);
      Serial.println(" mm.");
    }
    //===========================================================

    void processIncomingLine( char* line, int charNB ) {
      int currentIndex = 0;
      char buffer[ 64 ];                                 // Hope that 64 is enough for 1 parameter
      struct point newPos;

      newPos.x = 0.0;
      newPos.y = 0.0;

      //  Needs to interpret
      //  G1 for moving
      //  G4 P300 (wait 150ms)
      //  G1 X200 Y300
      //  G1 X300 Y200
      //  M300 S30 (pen down)
      //  M300 S50 (pen up)
      //  Discard anything with a (
      //  Discard any other command!

      while( currentIndex < charNB ) {
        switch ( line[ currentIndex++ ] ) {              // Select command, if any
        case 'U':
          penUp();
          break;
        case 'D':
          penDown();
          break;
        case 'G':
          buffer[0] = line[ currentIndex++ ];          // /!\ Dirty - Only works with 2 digit commands
          //      buffer[1] = line[ currentIndex++ ];
          //      buffer[2] = '\0';
          buffer[1] = '\0';

          switch ( atoi( buffer ) ){                   // Select G command
          case 0:                                   // G00 & G01 - Movement or fast movement. Same here
          case 1:
            // /!\ Dirty - Suppose that X is before Y
            char* indexX = strchr( line+currentIndex, 'X' );  // Get X/Y position in the string (if any)
            char* indexY = strchr( line+currentIndex, 'Y' );
            if ( indexY <= 0 ) {
              newPos.x = atof( indexX + 1);
              newPos.y = actuatorPos.y;
            }
            else if ( indexX <= 0 ) {
              newPos.y = atof( indexY + 1);
              newPos.x = actuatorPos.x;
            }
            else {
              newPos.y = atof( indexY + 1);
              indexY = '\0';
              newPos.x = atof( indexX + 1);
            }
            drawLine(newPos.x, newPos.y );
            //        Serial.println("ok");
            actuatorPos.x = newPos.x;
            actuatorPos.y = newPos.y;
            break;
          }
          break;
        case 'M':
          buffer[0] = line[ currentIndex++ ];        // /!\ Dirty - Only works with 3 digit commands
          buffer[1] = line[ currentIndex++ ];
          buffer[2] = line[ currentIndex++ ];
          buffer[3] = '\0';
          switch ( atoi( buffer ) ){
          case 300:
            {
              char* indexS = strchr( line+currentIndex, 'S' );
              float Spos = atof( indexS + 1);
              //          Serial.println("ok");
              if (Spos == 30) {
                penDown();
              }
              if (Spos == 50) {
                penUp();
              }
              break;
            }
          case 114:                                // M114 - Repport position
            Serial.print( "Absolute position : X = " );
            Serial.print( actuatorPos.x );
            Serial.print( "  -  Y = " );
            Serial.println( actuatorPos.y );
            break;
          default:
            Serial.print( "Command not recognized : M");
            Serial.println( buffer );
          }
        }
      }



    }


    /*********************************
     * Draw a line from (x0;y0) to (x1;y1).
     * Bresenham algo from https://www.marginallyclever.com/blog/2013/08/how-to-build-an-2-axis-arduino-cnc-gcode-interpreter/
     * int (x1;y1) : Starting coordinates
     * int (x2;y2) : Ending coordinates
     **********************************/
    void drawLine(float x1, float y1) {

      if (verbose)
      {
        Serial.print("fx1, fy1: ");
        Serial.print(x1);
        Serial.print(",");
        Serial.print(y1);
        Serial.println("");
      } 

      //  Bring instructions within limits
      if (x1 >= Xmax) {
        x1 = Xmax;
      }
      if (x1 <= Xmin) {
        x1 = Xmin;
      }
      if (y1 >= Ymax) {
        y1 = Ymax;
      }
      if (y1 <= Ymin) {
        y1 = Ymin;
      }

      if (verbose)
      {
        Serial.print("Xpos, Ypos: ");
        Serial.print(Xpos);
        Serial.print(",");
        Serial.print(Ypos);
        Serial.println("");
      }

      if (verbose)
      {
        Serial.print("x1, y1: ");
        Serial.print(x1);
        Serial.print(",");
        Serial.print(y1);
        Serial.println("");
      }

      //  Convert coordinates to steps
      x1 = (int)(x1*StepsPerMillimeterX);
      y1 = (int)(y1*StepsPerMillimeterY);
      float x0 = Xpos;
      float y0 = Ypos;

      //  Let's find out the change for the coordinates
      long dx = abs(x1-x0);
      long dy = abs(y1-y0);
      int sx = x0<x1 ? StepInc : -StepInc;
      int sy = y0<y1 ? StepInc : -StepInc;

      long i;
      long over = 0;

      if (dx > dy) {
        for (i=0; i<dx; ++i) {
          myStepperX.step(sx);
          over+=dy;
          if (over>=dx) {
            over-=dx;
            myStepperY.step(sy);
          }
          delay(StepDelay);
        }
      }
      else {
        for (i=0; i<dy; ++i) {
          myStepperY.step(sy);
          over+=dx;
          if (over>=dy) {
            over-=dy;
            myStepperX.step(sx);
          }
          delay(StepDelay);
        }   
      }

      if (verbose)
      {
        Serial.print("dx, dy:");
        Serial.print(dx);
        Serial.print(",");
        Serial.print(dy);
        Serial.println("");
      }

      if (verbose)
      {
        Serial.print("Going to (");
        Serial.print(x0);
        Serial.print(",");
        Serial.print(y0);
        Serial.println(")");
      }

      //  Delay before any next lines are submitted
      delay(LineDelay);
      //  Update the positions
      Xpos = x1;
      Ypos = y1;
    }

    //  Raises pen
    void penUp() {
      penServo.write(penZUp);
      delay(LineDelay);
      Zpos=Zmax;
      if (verbose) {
        Serial.println("Pen up!");
      }
    }
    //  Lowers pen
    void penDown() {
      penServo.write(penZDown);
      delay(LineDelay);
      Zpos=Zmin;
      if (verbose) {
        Serial.println("Pen down.");
      }
    }




    //==========================================================
    /**********************
     * void loop() - Main loop
     ***********************/
    void loop()
    {
      delay(200);
      char line[ LINE_BUFFER_LENGTH ];
      char c;
      int lineIndex;
      bool lineIsComment, lineSemiColon;

      lineIndex = 0;
      lineSemiColon = false;
      lineIsComment = false;

      while (1) {

        // Serial reception - Mostly from Grbl, added semicolon support
        while ( Serial.available()>0 ) {
          c = Serial.read();
          if (( c == '\n') || (c == '\r') ) {             // End of line reached
            if ( lineIndex > 0 ) {                        // Line is complete. Then execute!
              line[ lineIndex ] = '\0';                   // Terminate string
              if (verbose) {
                Serial.print( "Received : ");
                Serial.println( line );
              }
              processIncomingLine( line, lineIndex );
              lineIndex = 0;
            }
            else {
              // Empty or comment line. Skip block.
            }
            lineIsComment = false;
            lineSemiColon = false;
            Serial.println("ok");   
          }
          else {
            if ( (lineIsComment) || (lineSemiColon) ) {   // Throw away all comment characters
              if ( c == ')' )  lineIsComment = false;     // End of comment. Resume line.
            }
            else {
              if ( c <= ' ' ) {                           // Throw away whitepace and control characters
              }
              else if ( c == '/' ) {                    // Block delete not supported. Ignore character.
              }
              else if ( c == '(' ) {                    // Enable comments flag and ignore all characters until ')' or EOL.
                lineIsComment = true;
              }
              else if ( c == ';' ) {
                lineSemiColon = true;
              }
              else if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) {
                Serial.println( "ERROR - lineBuffer overflow" );
                lineIsComment = false;
                lineSemiColon = false;
              }
              else if ( c >= 'a' && c <= 'z' ) {        // Upcase lowercase
                line[ lineIndex++ ] = c-'a'+'A';
              }
              else {
                line[ lineIndex++ ] = c;
              }
            }
          }
        }
      }
    }

    i wszystko ruszyło ,teraz tylko porównam czym się różnią
  • Użytkownik usunął konto  
  • Poziom 4  
    Mój Arduino nano ma procesor Atmega328P i zawsze taki miał jak kupowałem, słyszałem ze Arduino mini może mieć Atmega168 ale ja jak kupiłem Arduino mini to też miał Atmega328P , teraz program bryka i wyglada ze się dogadał z moim Arduino,jak zmontuję całość i skalibruję to umieszczę na forum.
  • Użytkownik usunął konto  
  • Poziom 32  
    nowyARM napisał:
    marcinforty napisał:
    Mój Arduino nano ma procesor Atmega328P i zawsze taki miał jak kupowałem, słyszałem ze Arduino mini może mieć Atmega168 ale ja jak kupiłem Arduino mini to też miał Atmega328P , teraz program bryka i wyglada ze się dogadał z moim Arduino,jak zmontuję całość i skalibruję to umieszczę na forum.

    Jeden z pierwszych linków z Google
    https://pl.aliexpress.com/item/Pro-Mini-Modu-...030tSj4Mc2gVhweDI_EaAuRDEALw_wcB&gclsrc=aw.ds
    [Inne] Ploter na bazie Arduino nano

    Strasznie drogie to Arduino. Nano z Mega328 kosztuje ok 13zł. Podobny gabarytowo moduł z STM32F103 ok 15zł.
    - Atmega328: 32k flash 2k ram 1 usart 3 timery (2x8 i 1x 16 bit), 6PWM, 1 SPI, 1 ADC, zegar max 20MHz (1MIPS/MHz = 20MIPS)
    - 32F103: 64k flash, 20k ram, 3 usart, 4 timer 16 bit, 16PWM, 2 SPI, 2 ADC, 2 I2C, 1xCAN, CRC, RTC, USB, f max 72MHz (1.25DMIPS/MHz = 90DMIPS)
    Arduino Nano powinno kosztować 1 max 2zł.

    Jakby nie liczyć, to 2,5$ wynosi około 9zł po obecnym kursie a nie 13zl ;)

    Pozdr
  • Poziom 4  
    Jeżeli nie chcę kupować z Aliexpress ani czekać miesiąc na przesyłkę (przyjdzie lub nie ) to cena za arduino jest trochę wyższa w granicach 20 -50 zł ;)