Плоттер с ЧПУ НА базе ардуино, необходимо устранить ошибку (invalid conversion from 'char' to 'char*' [-fpermissive]indexY = '\0';

ВОТ КОД...

#include <Servo.h>
#include <AFMotor.h>

#define LINE_BUFFER_LENGTH 512

char STEP = MICROSTEP ;

// Положение сервопривода для подъема и опускания
const int penZUp = 95;
const int penZDown = 83;

// Сервопривод на ШИМ-выводе 10
const int penServoPin =10 ;

// Должно быть правильно для DVD-степперов, но здесь не слишком важно
const int stepsPerRevolution = 48; 

// создать объект сервопривода для управления сервоприводом 
Servo penServo;  

// Инициализируйте степперы для осей X и Y, используя эти контакты Arduino для H-моста L293D
AF_Stepper myStepperY(stepsPerRevolution,1);            
AF_Stepper myStepperX(stepsPerRevolution,2);  

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

// Текущее положение
struct point actuatorPos;

// Настройки рисования, должно быть OK
float StepInc = 1;
int StepDelay = 0;
int LineDelay =0;
int penDelay = 50;

// Мотор шагает на 1 миллиметр.
// Используйте тестовый скетч, чтобы пройти 100 шагов. Измерьте длину лески. 
// Рассчитать шаги на мм. Войдите сюда.
float StepsPerMillimeterX = 100.0;
float StepsPerMillimeterY = 100.0;

// Пределы чертежа робота, мм
// Хорошо, для начала. При хорошей калибровке может достигать 50 мм. 
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; 

// Установите значение true, чтобы получить отладочный вывод.
boolean verbose = false;

// Необходимо интерпретировать 
// G1 для перемещения
// G4 P300 (ожидание 150 мс)
// M300 S30 (ручка вниз)
// M300 S50 (ручка вверх)
// Отбросьте что-нибудь с (
// Отбросить любую другую команду!

/**********************
 * void setup() - Initialisations
 ***********************/
void setup() {
  // Настройка
  
  Serial.begin( 9600 );
  
  penServo.attach(penServoPin);
  penServo.write(penZUp);
  delay(100);

  // Уменьшить при необходимости
  myStepperX.setSpeed(600);

  myStepperY.setSpeed(600);  
  

  // Установить и переместить в исходное положение по умолчанию
  // ТБД

  // Уведомления!!!
  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() - Main loop
 ***********************/
void loop() 
{
  
  delay(100);
  char line[ LINE_BUFFER_LENGTH ];
  char c;
  int lineIndex;
  bool lineIsComment, lineSemiColon;

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

  while (1) {

    // Последовательный прием - В основном от Grbl, добавлена поддержка точки с запятой
    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) ) {   // Выбросить все символы комментария
          if ( c == ')' )  lineIsComment = false;     // Конец комментария. Возобновление линии.
        } 
        else {
          if ( c <= ' ' ) {                           // Выбросить пробелы и управляющие символы
          } 
          else if ( c == '/' ) {                    // Удаление блока не поддерживается. Игнорируйте символ.
          } 
          else if ( c == '(' ) {                    // Включить флаг комментариев и игнорировать все символы до ')' или 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 нижний регистр
            line[ lineIndex++ ] = c-'a'+'A';
          } 
          else {
            line[ lineIndex++ ] = c;
          }
        }
      }
    }
  }
}

void processIncomingLine( char* line, int charNB ) {
  int currentIndex = 0;
  char buffer[ 64 ];                                 // Надеюсь, что 64 достаточно для 1 параметра
  struct point newPos;

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

  // Необходимо интерпретировать 
  // G1 для перемещения
  // G4 P300 (ожидание 150 мс)
  // G1 X60 Y30
  // G1 X30 Y50
  // M300 S30 (ручка вниз)
  // M300 S50 (ручка вверх)
  // Отбросьте что-нибудь с (
  // Отбросить любую другую команду!

  while( currentIndex < charNB ) {
    switch ( line[ currentIndex++ ] ) {              // Выберите команду, если в любом
    case 'U':
      penUp(); 
      break;
    case 'D':
      penDown(); 
      break;
    case 'G':
      buffer[0] = line[ currentIndex++ ];          // /!\ Грязный - работает только с 2-значными командами
      // buffer[ 1] = строка [currentIndex++ ];
      // buffer[2] = '\0';
      buffer[1] = '\0';

      switch ( atoi( buffer ) ){                   //Выберите команду G
      case 0:                                   // G00 & G01 - Движение или быстрое движение. То же самое и здесь
      case 1:
        // /!\ Грязный - Предположим, что X находится перед Y
        char* indexX = strchr( line+currentIndex, 'X' );  // Получить позицию X/Y в строке (если таковая имеется)
        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("ок");
        actuatorPos.x = newPos.x;
        actuatorPos.y = newPos.y;
        break;
      }
      break;
    case 'M':
      buffer[0] = line[ currentIndex++ ];        ///!\ Грязный - работает только с 3-значными командами
      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("ок");
          if (Spos == 30) { 
            penDown(); 
          }
          if (Spos == 50) { 
            penUp(); 
          }
          break;
        }
      case 114:                                // M114 - Позиция возврата
        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("");
  }  

  // Приведите инструкции в определенные рамки
  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("");
  }

  // Преобразование координат в шаги
  x1 = (int)(x1*StepsPerMillimeterX);
  y1 = (int)(y1*StepsPerMillimeterY);
  float x0 = Xpos;
  float y0 = Ypos;

  // Выясним изменение для координат
  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.onestep(sx,STEP);
      over+=dy;
      if (over>=dx) {
        over-=dx;
        myStepperY.onestep(sy,STEP);
      }
    delay(StepDelay);
    }
  }
  else {
    for (i=0; i<dy; ++i) {
      myStepperY.onestep(sy,STEP);
      over+=dx;
      if (over>=dy) {
        over-=dy;
        myStepperX.onestep(sx,STEP);
      }
      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(penDelay); 
  Zpos=Zmax; 
  digitalWrite(15, LOW);
    digitalWrite(16, HIGH);
  if (verbose) { 
    Serial.println("Pen up!"); 
    
  } 
}
// Опускает pen
void penDown() { 
  penServo.write(penZDown); 
  delay(penDelay); 
  Zpos=Zmin; 
  digitalWrite(15, HIGH);
    digitalWrite(16, LOW);
  if (verbose) { 
    Serial.println("Pen down."); 
    
    
  } 
}

ВОТ В ЧЕМ ОШИБКА

C:\Users\Downloads\sketch_apr01a\sketch_apr01a.ino: In function 'void processIncomingLine(char*, int)':
C:\Users\Downloads\sketch_apr01a\sketch_apr01a.ino:224:20: warning: invalid conversion from 'char' to 'char*' [-fpermissive]
           indexY = '\0';
                    ^~~~

, 👍-1

Обсуждение

и что должна делать линия? Индексный[0] = '\0';?, @Juraj

Вы должны были хотя бы увидеть предупреждение относительно if ( indexY <= 0 ) { до ошибки, на которой вы сосредоточились. strchr не возвращает индекс; он возвращает указатель, который может быть или не быть нулевым указателем., @timemage


1 ответ


1

Строка должна гласить indexY[0] = '\0'; для компиляции. Но я думаю, что вы можете просто удалить всю строку, так как это манипулирует входным аргументом функции, который не используется дальше.

,