Há pouco tempo, eu estava preocupado com a questão de como fazer um acionamento para sistemas CNC em um motor coletor, e mesmo com feedback, e isso funcionaria no Modbus RTU.
Eu tinha à minha disposição o Arduino UNO, Driver for L298N, um motor coletor de um assento de carro da AEG para interruptores fotográficos de 12V e 2 intervalos.
Desde o início, soldei um cachecol com 2 interruptores fotográficos, de acordo com esse esquema.

Na forma finalizada, tudo se parece com isso:

A essência dessa coisa feia - uma partida atravessa o primeiro disjuntor desde o início, depois o segundo, para que o microcontrolador entenda em qual direção o motor gira.
Todas as conexões são assim:
d2 é o primeiro interruptor de foto;
d3 é o segundo interruptor de foto;
d5 - saída PWM para rotação para a esquerda;
d6 - saída PWM para rotação para a direita;
Tudo estava conectado e eu me sentei para escrever o código, no final do meu tormento deu à luz o seguinte:
#include <ModbusRtu.h> #define ID 1 // , , TX Modbus slave(ID, 0, 0); int8_t state = 0; // uint16_t au16data[11];// modbus #include <PID_v1.h> // double Setpoint1, Input1, Output1; double Setpoint2, Input2, Output2; double Kp = 1, Ki = 2.5, Kd = 0.5; PID myPID1(&Input1, &Output1, &Setpoint1, Kp, Ki, Kd, DIRECT); //1- PID myPID2(&Input2, &Output2, &Setpoint2, Kp, Ki, Kd, REVERSE); //2- int LeftPWM = 5; // int RightPWM = 6; // volatile byte EncA, EncB = 0; // volatile int Position = 0; // int SetPosition = 0; // void setup() { slave.begin(9600); pinMode (LeftPWM, OUTPUT); pinMode (RightPWM, OUTPUT); attachInterrupt(0, ChangePosition1, FALLING); // 0-(pin2) ChangePosition1() attachInterrupt(1, ChangePosition2, FALLING); // 1-(pin3) ChangePosition2() Setpoint1 = 0; Setpoint2 = 0; digitalWrite (LeftPWM, LOW); digitalWrite (RightPWM, LOW); } // 0 void ChangePosition1() // ! { EncA = 1; if (EncA == 1 && EncB == 1) { EncA = 0; EncB = 0; Position++; } } // 1 void ChangePosition2() { EncB = 1; if (EncA == 1 && EncB == 1) { EncA = 0; EncB = 0; Position--; } } void loop() { // ModBus // state = slave.poll(au16data, 11); // au16data[2] = Position;// // SetPosition = au16data[3];// // au16data[8] = slave.getInCnt(); // au16data[9] = slave.getOutCnt(); // au16data[10] = slave.getErrCnt();// if (SetPosition == Position) // { myPID1.SetMode(MANUAL); myPID2.SetMode(MANUAL); Output1 = 0; Output2 = 0; digitalWrite (LeftPWM, LOW); digitalWrite (RightPWM, LOW); } if (SetPosition < Position) { myPID2.SetMode(AUTOMATIC); Setpoint2 = SetPosition; Input2 = Position; myPID2.Compute(); analogWrite (LeftPWM, Output2); digitalWrite (RightPWM, LOW); } if (SetPosition > Position) { myPID1.SetMode(AUTOMATIC); Setpoint1 = SetPosition; Input1 = Position; myPID1.Compute(); analogWrite (RightPWM, Output1); digitalWrite (LeftPWM, LOW); } }
E agora é parte por parte no computador. O SinplLight SCADA foi escolhido pelos caras para fazer tudo mudar de graça. Então - é assim que as configurações do scud são exibidas.



A interface foi feita assim:

Como resultado, colocamos o motor subordinado ao controle deslizante no acelerador, acelera e freia o motor suavemente; se você rolar manualmente a âncora, ele não permitirá isso e retornará. Obrigado pela atenção. E aqui está uma visão geral da bagunça.
