diff --git a/.gitignore b/.gitignore index 89cc49c..ccbd82f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch + +include/credenciais.h \ No newline at end of file diff --git a/data/gcode.txt b/data/gcode.txt index 6adc255..563d8b7 100644 --- a/data/gcode.txt +++ b/data/gcode.txt @@ -1,3 +1,11 @@ -G01 X100.00 Y0 Z0 F1000 -G01 X250.00 Y0 Z0 F1000 -G01 X200.00 Y0 Z0 F1000 +G00 X0 Y0 Z0 F1000 +G00 X5 Y0 Z0 + +G01 X5 Y0 Z-30 +G01 X5 Y-5 Z-30 +G01 X50 Y-5 Z-30 +G01 X50 Y-50 Z-30 +G01 X5 Y-5 Z-30 + +G01 X5 Y-5 Z0 +G00 X0 Y0 Z0 diff --git a/include/controlador.h b/include/controlador.h index 892f728..5a71432 100644 --- a/include/controlador.h +++ b/include/controlador.h @@ -3,6 +3,7 @@ #include "AccelStepper.h" #include "sensor_curso.h" +#include "GCodeParser.h" // Velocidade máxima de deslocamento #define MAX_SPEED 30000.0 @@ -10,9 +11,9 @@ // Resolução de passo de cada eixo #define STEPS_POR_MM_X 4.750893824 // 2pi/200*R #define STEPS_POR_MM_Y 4.486397268 -#define STEPS_POR_MM_Z 1.0 +#define Z_CANETA_BAIXA -30 -// Margem de caibração no eixo X +// Margem de caibração no eixo X (em steps) #define MARGEM_X 10 // Período da Task do controlador @@ -25,7 +26,8 @@ class Controlador { public: Controlador(int pinStepX, int pinDirX, int pinStepY, int pinDirY, int pinStepZ, int pinDirZ); void iniciarControlador(); - void enviarComando(int G, float X, float Y, float Z); + // void enviarComando(int G, float X, float Y, float Z); + void enviarComando(GCodeParser *pGCode); void calibrar(); void cancelar(); void origem(); @@ -37,7 +39,7 @@ class Controlador { AccelStepper *pStepperZ; // velocidade de deslocamento - float speed = 5000.0; + float speed = 50.0; // TODO calcular velocidade efetiva // flags de controle bool calibrando = false; diff --git a/include/interface_wifi.h b/include/interface_wifi.h index 1d7f0c5..ed0e80f 100644 --- a/include/interface_wifi.h +++ b/include/interface_wifi.h @@ -14,6 +14,8 @@ class InterfaceWiFi { static String processor(const String& var); static void handleEstado(AsyncWebServerRequest *request); + bool carregando = false; + private: AsyncWebServer server; }; diff --git a/include/maquina_estados.h b/include/maquina_estados.h index 5de26f0..7f0c68e 100644 --- a/include/maquina_estados.h +++ b/include/maquina_estados.h @@ -54,6 +54,31 @@ typedef enum Acao { A05 } Acao; +const String estados_str[] = { + "Idle", + "Imprimindo", + "Calibrando" + }; + +const String eventos_str[] = { + "Nenhum evento", + "Calibrar", + "Imprimir", + "Cancelar", + "Terminado", + "Origem", + "Carregar" +}; + +const String acoes_str[] = { + "Nenhuma ação", + "A01", + "A02", + "A03", + "A04", + "A05" +}; + /** * @brief Struct que armazena o próximo estado e a ação a ser realizada * diff --git a/src/controlador.cpp b/src/controlador.cpp index 9820b15..f617d8d 100644 --- a/src/controlador.cpp +++ b/src/controlador.cpp @@ -17,6 +17,8 @@ Controlador::Controlador(int pinStepX, int pinDirX, int pinStepY, int pinDirY, i pStepperX->setMaxSpeed(MAX_SPEED); pStepperY->setMaxSpeed(MAX_SPEED); pStepperZ->setMaxSpeed(MAX_SPEED); + + pStepperY->setPinsInverted(true, false, false); } void Controlador::iniciarControlador() @@ -34,11 +36,31 @@ void Controlador::iniciarControlador() ); } -void Controlador::enviarComando(int G, float X, float Y, float Z) +// void Controlador::enviarComando(int G, float X, float Y, float Z) +void Controlador::enviarComando(GCodeParser *pGCode) { - int stepsX = (int) round(X * STEPS_POR_MM_X); - int stepsY = (int) round(Y * STEPS_POR_MM_Y); - int stepsZ = (int) round(Z * STEPS_POR_MM_Z); + static int G = -1; + static int stepsX, stepsY, stepsZ; + + if (pGCode->HasWord('G')) { + G = pGCode->GetWordValue('G'); + } + if (pGCode->HasWord('X')) { + int X = pGCode->GetWordValue('X'); + stepsX = (int) round(X * STEPS_POR_MM_X); + } + if (pGCode->HasWord('Y')) { + int Y = pGCode->GetWordValue('Y'); + stepsY = (int) round(Y * STEPS_POR_MM_Y); + } + if (pGCode->HasWord('Z')) { + int Z = pGCode->GetWordValue('Z'); + if (Z >= 0) { + stepsZ = 0; + } else { + stepsZ = Z_CANETA_BAIXA; + } + } Serial.printf("[Controlador] G%d stepsX=%d stepsY=%d stepsZ=%d\n", G, stepsX, stepsY, stepsZ); @@ -57,7 +79,7 @@ void Controlador::enviarComando(int G, float X, float Y, float Z) pStepperY->moveTo(stepsY); pStepperZ->moveTo(stepsZ); - // Velocidades para trajetoria reta XY + // Velocidades para trajetoria reta no plano XY float dist = sqrt(pow(stepsX - pStepperX->currentPosition(),2) + pow(stepsY - pStepperY->currentPosition(),2) ); @@ -68,6 +90,7 @@ void Controlador::enviarComando(int G, float X, float Y, float Z) pStepperY->setSpeed(speedY); pStepperZ->setSpeed(speed); } + // TODO arcos mover = true; } @@ -81,18 +104,19 @@ void Controlador::calibrar() Serial.println("[Controlador] Iniciando calibração"); pStepperX->setSpeed(-speed); - pStepperY->setSpeed(-speed); - pStepperZ->setSpeed(-speed); } void Controlador::cancelar() { + // TODO levantar caneta movendo = false; flag_cancelar = true; + Serial.println("[Controlador] Cancelando movimento"); } void Controlador::taskControlar() { + // TODO quando terminar jogar o papel pra fora xSemaphoreGive(xSemaphoreControlador); TickType_t xLastWakeTime; @@ -119,8 +143,8 @@ void Controlador::taskControlar() if (xSemaphoreGive(xSemaphoreControlador) != pdTRUE) { Serial.println("[Controlador] Falha ao ceder semáforo"); } - Serial.println("[Controlador] Movimento cancelado"); flag_cancelar = false; + Serial.println("[Controlador] Movimento cancelado"); } if (movendo) { if ((pStepperX->distanceToGo() != 0) || (pStepperY->distanceToGo() != 0) || (pStepperZ->distanceToGo() != 0)) { @@ -146,8 +170,6 @@ void Controlador::taskControlar() calibrando = false; } pStepperX->runSpeed(); - pStepperY->runSpeed(); - pStepperZ->runSpeed(); } // Delay para obter frequência constante vTaskDelayUntil(&xLastWakeTime, xFrequency); diff --git a/src/interface_wifi.cpp b/src/interface_wifi.cpp index 46da7f0..c0912ec 100644 --- a/src/interface_wifi.cpp +++ b/src/interface_wifi.cpp @@ -14,11 +14,12 @@ void InterfaceWiFi::iniciarWiFi() // Conectar no WiFI WiFi.begin(SSID, PASSWORD); + Serial.print("[InterfaceWiFi] Conectando no WiFi..."); while (WiFi.status() != WL_CONNECTED) { delay(1000); - Serial.println("[InterfaceWiFi] Conectando no WiFi..."); + Serial.print("."); } - Serial.print("[InterfaceWiFi] Conectado no IP: "); + Serial.print("\n[InterfaceWiFi] Conectado no IP: "); Serial.println(WiFi.localIP()); // Página principal @@ -66,50 +67,61 @@ void InterfaceWiFi::iniciarWiFi() void InterfaceWiFi::imprimir() { Evento evento = IMPRIMIR; - while(xQueueSendToBack(xQueueEventos, &evento, portMAX_DELAY) != pdTRUE); + if(xQueueSendToBack(xQueueEventos, &evento, portMAX_DELAY) != pdTRUE) { + Serial.println("[InterfaceWiFi] Erro ao enviar evento à fila"); + } } void InterfaceWiFi::cancelar() { Evento evento = CANCELAR; - while(xQueueSendToBack(xQueueEventos, &evento, portMAX_DELAY) != pdTRUE); -} + if(xQueueSendToBack(xQueueEventos, &evento, portMAX_DELAY) != pdTRUE) { + Serial.println("[InterfaceWiFi] Erro ao enviar evento à fila"); + }} void InterfaceWiFi::calibrar() { Evento evento = CALIBRAR; - while(xQueueSendToBack(xQueueEventos, &evento, portMAX_DELAY) != pdTRUE); -} + if(xQueueSendToBack(xQueueEventos, &evento, portMAX_DELAY) != pdTRUE) { + Serial.println("[InterfaceWiFi] Erro ao enviar evento à fila"); + }} void InterfaceWiFi::carregarPrograma(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { - if (maquinaEstados.getEstado() == IDLE) { - // https://github.com/smford/esp32-asyncwebserver-fileupload-example/blob/master/example-01/example-01.ino - String logmessage = "[InterfaceWiFi] Client:" + request->client()->remoteIP().toString() + " " + request->url(); - Serial.println(logmessage); - - if (!index) { - logmessage = "[InterfaceWiFi] Upload Start: " + String(filename); - // open the file on first call and store the file handle in the request object - // request->_tempFile = SPIFFS.open("/" + filename, "w"); - request->_tempFile = SPIFFS.open("/gcode.txt", "w"); - Serial.println(logmessage); + if (!interfaceWifi.carregando) { + Evento evento = CARREGAR; + if(xQueueSendToBack(xQueueEventos, &evento, portMAX_DELAY) != pdTRUE) { + Serial.println("[InterfaceWiFi] Erro ao enviar evento à fila"); } + } - if (len) { - // stream the incoming chunk to the opened file - request->_tempFile.write(data, len); - logmessage = "[InterfaceWiFi] Writing file: " + String(filename) + " index=" + String(index) + " len=" + String(len); - Serial.println(logmessage); - } + while(!interfaceWifi.carregando) vTaskDelay(pdMS_TO_TICKS(100)); - if (final) { - logmessage = "[InterfaceWiFi] Upload Complete: " + String(filename) + ",size: " + String(index + len); - // close the file handle as the upload is now done - request->_tempFile.close(); - Serial.println(logmessage); - request->redirect("/"); - } + // https://github.com/smford/esp32-asyncwebserver-fileupload-example/blob/master/example-01/example-01.ino + String logmessage = "[InterfaceWiFi] Client: " + request->client()->remoteIP().toString() + " " + request->url(); + Serial.println(logmessage); + + if (!index) { + logmessage = "[InterfaceWiFi] Upload Start: " + String(filename); + // open the file on first call and store the file handle in the request object + request->_tempFile = SPIFFS.open("/gcode.txt", "w"); + Serial.println(logmessage); + } + + if (len) { + // stream the incoming chunk to the opened file + request->_tempFile.write(data, len); + logmessage = "[InterfaceWiFi] Writing file: " + String(filename) + " index=" + String(index) + " len=" + String(len); + Serial.println(logmessage); + } + + if (final) { + logmessage = "[InterfaceWiFi] Upload Complete: " + String(filename) + ",size: " + String(index + len); + // close the file handle as the upload is now done + request->_tempFile.close(); + Serial.println(logmessage); + request->redirect("/"); + interfaceWifi.carregando = false; } } diff --git a/src/interpretador_g.cpp b/src/interpretador_g.cpp index 51cf91e..2eb6138 100644 --- a/src/interpretador_g.cpp +++ b/src/interpretador_g.cpp @@ -34,6 +34,7 @@ void InterpretadorG::cancelar() { imprimindo = false; file.close(); + Serial.println("[InterpretadorG] Impressão cancelada"); } void InterpretadorG::taskExecutar() @@ -46,8 +47,7 @@ void InterpretadorG::taskExecutar() } while(1) { - if (imprimindo && (xSemaphoreControlador != NULL)) { // estado Imprimindo - // Serial.println("[InterpretadorG] Aguardando semáforo"); + if (imprimindo) { // estado Imprimindo if (xSemaphoreTake(xSemaphoreControlador, (TickType_t) 0) == pdTRUE) { Serial.println("[InterpretadorG] Semáforo capturado"); if (file.available()) { @@ -57,20 +57,8 @@ void InterpretadorG::taskExecutar() GCode.ParseLine(); Serial.println("[InterpretadorG] Linha lida"); - if (GCode.HasWord('G')) { - G = GCode.GetWordValue('G'); - } - if (GCode.HasWord('X')) { - X = GCode.GetWordValue('X'); - } - if (GCode.HasWord('Y')) { - Y = GCode.GetWordValue('Y'); - } - if (GCode.HasWord('Z')) { - Z = GCode.GetWordValue('Z'); - } - - controlador.enviarComando(G, X, Y, Z); + // controlador.enviarComando(G, X, Y, Z); + controlador.enviarComando(&GCode); } else { // quando termina a última linha Serial.println("[InterpretadorG] Programa terminado"); diff --git a/src/main.cpp b/src/main.cpp index e4fb8d1..73c62da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -90,12 +90,6 @@ void setup() { } void loop() { - // static int i = 0; - // Serial.print("Hello World! "); - // Serial.print(i++); - // Serial.print("\t"); - // Serial.println(sensorCurso1.origem()); - // vTaskDelay(pdMS_TO_TICKS(5000)); } diff --git a/src/maquina_estados.cpp b/src/maquina_estados.cpp index 7e8c90c..8fc9a66 100644 --- a/src/maquina_estados.cpp +++ b/src/maquina_estados.cpp @@ -1,5 +1,7 @@ #include + #include "maquina_estados.h" +#include "interface_wifi.h" void MaquinaEstados::iniciarMaquinaEstados() { @@ -27,10 +29,12 @@ void MaquinaEstados::iniciarMaquinaEstados() matrizTransicaoEstados[IDLE][IMPRIMIR].acao = A03; // Imprimindo - matrizTransicaoEstados[IMPRIMINDO][TERMINADO].estado = CALIBRANDO; - matrizTransicaoEstados[IMPRIMINDO][TERMINADO].acao = A02; + // matrizTransicaoEstados[IMPRIMINDO][TERMINADO].estado = CALIBRANDO; + // matrizTransicaoEstados[IMPRIMINDO][TERMINADO].acao = A02; + matrizTransicaoEstados[IMPRIMINDO][TERMINADO].estado = IDLE; + matrizTransicaoEstados[IMPRIMINDO][TERMINADO].acao = A04; - matrizTransicaoEstados[IMPRIMINDO][CANCELAR].estado = CALIBRANDO; + matrizTransicaoEstados[IMPRIMINDO][CANCELAR].estado = IDLE; matrizTransicaoEstados[IMPRIMINDO][CANCELAR].acao = A05; // Calibrando @@ -44,7 +48,7 @@ void MaquinaEstados::iniciarMaquinaEstados() xTaskCreate( vTaskMaquinaEstados, "Máquina de Estados", - 10000, + 20000, this, 2, NULL @@ -61,6 +65,9 @@ void MaquinaEstados::executarAcao(Acao acao) { break; case A01: // Carregar programa Serial.println("[MaquinaEstados] Carregando programa"); + interfaceWifi.carregando = true; + while(interfaceWifi.carregando) vTaskDelay(pdMS_TO_TICKS(100)); + Serial.println("[MaquinaEstados] Programa carregado"); break; case A02: // Calibrar Serial.println("[MaquinaEstados] Iniciando calibração"); @@ -76,8 +83,7 @@ void MaquinaEstados::executarAcao(Acao acao) { case A05: Serial.println("[MaquinaEstados] Cancelando impressão"); interpretadorG.cancelar(); - Serial.println("[MaquinaEstados] Iniciando calibração"); - controlador.calibrar(); + controlador.cancelar(); break; } } @@ -90,27 +96,21 @@ Estado MaquinaEstados::getEstado() void MaquinaEstados::taskExecutar() { while (1) { - // Serial.println("[MaquinaEstados] Ciclo"); Evento evento; - if (xQueueReceive(xQueueEventos, &evento, portMAX_DELAY) == pdTRUE) { - Serial.println("[MaquinaEstados] Evento recebido"); - } else { + if (xQueueReceive(xQueueEventos, &evento, portMAX_DELAY) != pdTRUE) { Serial.println("[MaquinaEstados] Falha ao receber evento"); } if (evento != NENHUM_EVENTO) { ProxEstadoAcao proxEstadoAcao = obterProxEstadoAcao(estado, evento); + Serial.printf("[MaquinaEstados] Evento: %s; Estado: %s; Ação: %s\n", + eventos_str[evento], + estados_str[proxEstadoAcao.estado], + acoes_str[proxEstadoAcao.acao] + ); - Serial.print("[MaquinaEstados] Estado: "); - Serial.print(proxEstadoAcao.estado); - Serial.print("\tEvento: "); - Serial.print(evento); - Serial.print("\tAcao: "); - Serial.println(proxEstadoAcao.acao); - executarAcao(proxEstadoAcao.acao); estado = proxEstadoAcao.estado; } - // vTaskDelay(FSM_DELAY / portTICK_PERIOD_MS); } }