#include "C:\Zendion Inc\agrobot_base\Firmware\Modulos\SerialService.h" #define D_Code Dir #define _pinoLED RGB_BUILTIN int _pinoReleGeral = 8; long _baudRate = 115200; bool Conectado = false; int _TaxaAmostragem; int PPR = 12800; // Pulsos por revolução int FrequenciaMaxima = 10000; double _Margem = 0.5; class Motor { public: // Construtor Motor(String desc) { _ID = desc; } // Definições String _ID; int _canal; int _pinoENA; int _pinoDIR; int _pinoPUL; int _pinoEncoderA; int _pinoEncoderB; int _pinoRef000; int _pinoRef090; int _pinoRef270; bool Iniciado = false; bool Testando = false; bool Referenciando = false; // Consumo double _Angulo; Sentido _Sentido; // Entrada de dados double _Angulo_SP; double _Angulo_Offset = 0; Sentido _Sentido_SP = Parado; bool _RampaAtivada = false; int dutyCycle = 512; double _frequencia = 4000; bool _Estabilizar = true; bool Ag0 = false; bool Ag0Ref = false; bool Ag90 = false; bool Ag270 = false; bool Referenciado = false; int RefMax = 90; int RefMin = -90; int ulEncoderA = 0; int ulEncoderB = 0; double GrausPino = 0; void Inicializar() { if (Iniciado) { EnviarDadosSerial(_ID + " ja inicializado"); EnviarDadosSerial(MontarProtocoloSensor(sCFG, _ID, Iniciado ? "1" : "0")); return; } if (_pinoPUL > -1) { AtualizarPWM(); } if (_pinoENA > -1) { pinMode(_pinoENA, OUTPUT); digitalWrite(_pinoENA, HIGH); } if (_pinoDIR > -1) { pinMode(_pinoDIR, OUTPUT); digitalWrite(_pinoDIR, LOW); } if (_pinoEncoderA > -1) { pinMode(_pinoEncoderA, INPUT); ulEncoderA = digitalRead(_pinoEncoderA); } if (_pinoEncoderB > -1) { pinMode(_pinoEncoderB, INPUT); ulEncoderB = digitalRead(_pinoEncoderB); } if (_pinoRef000 > -1) { pinMode(_pinoRef000, INPUT); Ag0 = digitalRead(_pinoRef000) == 1; } if (_pinoRef090 > -1) { pinMode(_pinoRef090, INPUT); Ag90 = digitalRead(_pinoRef090) == 1; } if (_pinoRef270 > -1) { pinMode(_pinoRef270, INPUT); Ag270 = digitalRead(_pinoRef270) == 1; } xTaskCreatePinnedToCore(&Motor::RampaTaskWrapper, "RampaTask", 5000, this, _canal, &RampaTaskHandle, 0); _Angulo = 0; GrausPino = 0; _Sentido_SP = Parado; _Sentido = Parado; Referenciado = false; Referenciando = true; _RampaAtivada = true; Iniciado = true; EnviarDadosSerial(MontarProtocoloSensor(sCFG, _ID, Iniciado ? "1" : "0")); } void AtualizarPWM() { ledcSetup(_canal, _frequencia, 10); ledcAttachPin(_pinoPUL, _canal); ledcWrite(_canal, dutyCycle); } void Desligar() { if (!Iniciado) { EnviarDadosSerial(_ID + " nao esta inicializado"); EnviarDadosSerial(MontarProtocoloSensor(sCFG, _ID, Iniciado ? "1" : "0")); return; } // Parar a execução das tarefas vTaskDelete(RampaTaskHandle); // Redefinir as configurações para os valores iniciais if (_pinoENA > -1) { pinMode(_pinoENA, INPUT); } if (_pinoDIR > -1) { pinMode(_pinoDIR, INPUT); } if (_pinoPUL > -1) { ledcDetachPin(_pinoPUL); pinMode(_pinoPUL, INPUT); } if (_pinoEncoderA > -1) { pinMode(_pinoEncoderA, INPUT); } if (_pinoEncoderB > -1) { pinMode(_pinoEncoderB, INPUT); } if (_pinoRef000 > -1) { pinMode(_pinoRef000, INPUT); } if (_pinoRef090 > -1) { pinMode(_pinoRef090, INPUT); } if (_pinoRef270 > -1) { pinMode(_pinoRef270, INPUT); } EnviarDadosSerial(_ID + " Desligado"); Iniciado = false; EnviarDadosSerial(MontarProtocoloSensor(sCFG, _ID, Iniciado ? "1" : "0")); } void Testar() { Testando = true; Testando = false; } private: TaskHandle_t RampaTaskHandle = NULL; static void RampaTaskWrapper(void *pvParameters) { Motor *motor = static_cast(pvParameters); motor->RampaTask(); } void RampaTask() { unsigned long previousMillisRampa = millis(); while (1) { if (!Conectado) { // Caso não esteja conectado, aguarda 1 segundo até a próxima verificação, liberando uso de CPU vTaskDelay(1000); continue; } AferirPosicao(); if (Referenciando) { ReferenciarMotor(); } else { VerificarAnguloSP(); } Atualizar(); unsigned long currentMillis = millis(); if (currentMillis - previousMillisRampa >= _TaxaAmostragem) { previousMillisRampa = currentMillis; EnviarDadosSerial(MontarProtocoloSensor(sENC, _ID, MontarDadosProtocoloEncoder(_Sentido, _Angulo, Ag0, Ag90, Ag270, GrausPino))); } } } void Atualizar() { if (_pinoENA > -1) { digitalWrite(_pinoENA, !_RampaAtivada); } if (_pinoDIR > -1) { digitalWrite(_pinoDIR, _Sentido_SP != Horario); } } void AferirPosicao() { if (_pinoRef000 > -1) { bool _Ag0 = digitalRead(_pinoRef000) == 1; if (GrausPino == 0) { if (_Ag0 && !Ag0) { _Angulo = 0; } else if (!_Ag0 && Ag0) { GrausPino = (_Angulo < 0 ? -1.0 : 1.0) * _Angulo; _Angulo = ((GrausPino / 2.0) * (_Sentido_SP == Horario ? 1.0 : -1.0)) + _Angulo_Offset; Referenciado = true; } } /*else { if ((!Ag0 && _Ag0) || (Ag0 && !_Ag0)) { // Entrou no pino ou saiu do pino _Angulo = (((GrausPino / 2.0) + _Angulo_Offset) * (_Sentido_SP == Horario ? -1.0 : 1.0)); Referenciado = true; } }*/ Ag0 = _Ag0; } if (_pinoRef090 > -1) { Ag90 = digitalRead(_pinoRef090) == 1; } if (_pinoRef270 > -1) { Ag270 = digitalRead(_pinoRef270) == 1; } if (_pinoEncoderA > -1 && _pinoEncoderB > -1) { int leituraEncoderA = digitalRead(_pinoEncoderA); int leituraEncoderB = digitalRead(_pinoEncoderB); // Verifica o sentido do giro if (leituraEncoderA != ulEncoderA && leituraEncoderA == 1) { if (leituraEncoderB != leituraEncoderA) { // Sentido horário _Angulo++; _Sentido = Horario; } else { // Sentido anti-horário _Angulo--; _Sentido = Antihorario; } if (_Angulo_SP == 0 && (_Angulo >= -_Margem && _Angulo <= _Margem) && Referenciado) { _Sentido_SP = Parado; _Sentido = Parado; _RampaAtivada = false; } } if (leituraEncoderA != ulEncoderA) { ulEncoderA = leituraEncoderA; } if (leituraEncoderB != ulEncoderB) { ulEncoderB = leituraEncoderB; } } } void VerificarAnguloSP() { if (_RampaAtivada) { if (_Angulo_SP > -1) { if (_Sentido_SP == Horario && ((_Angulo >= _Angulo_SP) || (Referenciado && _Angulo > RefMax))) { _RampaAtivada = false; } else if (_Sentido_SP == Antihorario && ((_Angulo <= (_Angulo_SP * -1)) || (Referenciado && _Angulo < RefMin))) { _RampaAtivada = false; } } } else { if (_Estabilizar && _Sentido_SP == Parado && _Angulo != _Angulo_SP) { _Sentido_SP = _Angulo > 0 ? Antihorario : Horario; _RampaAtivada = true; } } } void ReferenciarMotor() { int AgP1 = 45; int AgP2 = 90; if (Referenciado && (_Angulo >= -_Margem && _Angulo <= _Margem)) { Referenciando = false; _RampaAtivada = false; } else { if (Ag90) { _Angulo = 90 + (((GrausPino / 2.0) * (_Sentido_SP == Horario ? 1.0 : -1.0)) + _Angulo_Offset); _Angulo_SP = AgP2; _Sentido_SP = Antihorario; } else if (Ag270) { _Angulo = -90 + (((GrausPino / 2.0) * (_Sentido_SP == Horario ? 1.0 : -1.0)) + _Angulo_Offset); _Angulo_SP = AgP2; _Sentido_SP = Horario; } else if (_Sentido_SP == Parado && (_Angulo >= -_Margem && _Angulo <= _Margem)) { _Angulo_SP = AgP1; _Sentido_SP = Horario; } else if (_Sentido_SP == Horario) { if (_Angulo >= AgP1) { _Angulo_SP = AgP1; _Sentido_SP = Antihorario; } } else if (_Sentido_SP == Antihorario) { if (_Angulo <= -AgP1) { _Angulo_SP = AgP2; _Sentido_SP = Antihorario; } else if (_Angulo <= -AgP2) { _Angulo_SP = AgP2; _Sentido_SP = Horario; } } } } }; Motor M1("ET"); Motor M2("EF"); Motor M3("DT"); Motor M4("DF"); void setup() { Serial.begin(_baudRate); pinMode(_pinoReleGeral, OUTPUT); digitalWrite(_pinoReleGeral, LOW); } void loop() { if (Serial.available() > 3) { String Protocolo = ""; F_Code _funcao = Nda; while (Serial.available()) { char Entrada = (char)Serial.read(); if (Entrada == EndLine) { break; } Protocolo += Entrada; if (Protocolo.length() == 3) { if (_funcao == Nda) { _funcao = (F_Code)((String)Protocolo[0] + (String)Protocolo[1] + (String)Protocolo[2]).toInt(); Protocolo = ""; } } } EnviarDadosSerial("OK"); if (_funcao == Chk) { EnviarDadosSerial(MontarProtocoloVerificacao(D_Code)); } else if (_funcao == Cfg) { String ID = ((String)Protocolo[0] + (String)Protocolo[1]); bool Conectar = (String)Protocolo[3] == "1"; if (ID == "MD") { _TaxaAmostragem = ((String)Protocolo[5] + (String)Protocolo[6] + (String)Protocolo[7] + (String)Protocolo[8] + (String)Protocolo[9]).toInt(); int pinoReleGeral = ((String)Protocolo[11] + (String)Protocolo[12]).toInt(); int _PPR = ((String)Protocolo[14] + (String)Protocolo[15] + (String)Protocolo[16] + (String)Protocolo[17] + (String)Protocolo[18]).toInt(); PPR = _PPR; if (pinoReleGeral > -1) { pinMode(_pinoReleGeral, INPUT); _pinoReleGeral = pinoReleGeral; pinMode(_pinoReleGeral, OUTPUT); digitalWrite(_pinoReleGeral, Conectar); } vTaskDelay(pdMS_TO_TICKS(100)); Conectado = Conectar; EnviarDadosSerial(MontarProtocoloSensor(sCFG, "MD", Conectado ? "1" : "0")); } else { Motor* _motor = ID == "ET" ? &M1 : ID == "EF" ? &M2 : ID == "DT" ? &M3 : &M4; int canal = ((String)Protocolo[5]).toInt(); bool motor_ativado = (String)Protocolo[7] == "1"; bool estabilizar = ((String)Protocolo[9]) == "1"; int pul = ((String)Protocolo[11] + (String)Protocolo[12]).toInt(); int dir = ((String)Protocolo[14] + (String)Protocolo[15]).toInt(); int ena = ((String)Protocolo[17] + (String)Protocolo[18]).toInt(); int encoderA = ((String)Protocolo[20] + (String)Protocolo[21]).toInt(); int encoderB = ((String)Protocolo[23] + (String)Protocolo[24]).toInt(); int ref0 = ((String)Protocolo[26] + (String)Protocolo[27]).toInt(); int ref90 = ((String)Protocolo[29] + (String)Protocolo[30]).toInt(); int ref270 = ((String)Protocolo[32] + (String)Protocolo[33]).toInt(); if (motor_ativado) { if (Conectar) { _motor->_canal = canal; _motor->_Estabilizar = estabilizar; _motor->_pinoPUL = pul; _motor->_pinoDIR = dir; _motor->_pinoENA = ena; _motor->_pinoEncoderA = encoderA; _motor->_pinoEncoderB = encoderB; _motor->_pinoRef000 = ref0; _motor->_pinoRef090 = ref90; _motor->_pinoRef270 = ref270; _motor->Inicializar(); } else { _motor->Desligar(); } vTaskDelay(pdMS_TO_TICKS(500)); } } } else if (_funcao == Cmd) { //canal;sentido;angulo //0;0;000.00 String ID = ((String)Protocolo[0] + (String)Protocolo[1]); Motor* _motor = ID == "ET" ? &M1 : ID == "EF" ? &M2 : ID == "DT" ? &M3 : &M4; int porcentagem = ((String)Protocolo[9] + (String)Protocolo[10] + (String)Protocolo[11]).toInt(); double frequencia = (porcentagem / 100.0) * FrequenciaMaxima; _motor->_Sentido_SP = (Sentido)((String)Protocolo[3]).toInt(); _motor->_Angulo_SP = ((String)Protocolo[5] + (String)Protocolo[6] + (String)Protocolo[7]).toInt(); _motor->_frequencia = frequencia; _motor->_Angulo_Offset = ((String)Protocolo[13] + (String)Protocolo[14] + (String)Protocolo[15] + (String)Protocolo[16]).toInt(); _motor->AtualizarPWM(); _motor->_RampaAtivada = true; } else if (_funcao == Tst) { String ID = ((String)Protocolo[0] + (String)Protocolo[1]); Motor* _motor = ID == "ET" ? &M1 : ID == "EF" ? &M2 : ID == "DT" ? &M3 : &M4; bool EmTeste = _motor->Testando; if (!EmTeste) { _motor->Testar(); } } } }