Olá, estou montando um projeto de spin-coater usando um HD como motor, pra isso tenho um código um pouco complexo, pois envolver muitas coisas, porém meu programa apresentar alguns bugs, e não consigo reconhecer. Ao iniciar a ciclagem ele demora certo tempo pra mostrar o tempo e também quando vou fazer a interrupção também.
#include <Arduino.h>
#include <Servo.h>
#include "config.h"
#include "display.h"
#include "Encoder.h"
Servo esc;
int pinomotor = PINESC;
#define TROTTLEMIN 750 // 75
#define TROTTLEMAX 2000 // 170
void varia(int vel2);
void pisca(int n);
void testaRPM(int vel, int vel2, long tempo);
void setupBrushless()
{
esc.attach(pinomotor);
esc.writeMicroseconds(TROTTLEMAX);
delay(4000);
esc.writeMicroseconds(TROTTLEMIN);
delay(4000);
}
void loopBrushless()
{
varia(150);
delay(10000); // espera o ESC apitar
pisca(2);
varia(80);
delay(10000); // espera o ESC apitar
}
int vel = 0;
boolean onRPM(int vel2, long tempo)
{
int deltaT = 15;//30;
for(; vel<vel2;vel++){
esc.write(vel);
delay(deltaT); //
}
for(; vel>vel2;vel--){
esc.write(vel);
delay(deltaT); //
}
//lcd.print("...");
long t0 = millis();
long corrido = 0;
while( corrido < UNIDADE_TEMPO_MS*tempo){
if (onClick(PINENC_SW))
return false;
else{
sprintf(buffer,"%02d:%02d", corrido/60000,1);
lcd.setCursor(11,1);
sprintf(buffer,"%02d", corrido/60000);
lcd.print(buffer);
lcd.print(":");
sprintf(buffer,"%02d", (corrido/1000)%60);
lcd.print(buffer);
}
corrido = millis() - t0;
}
lcd.setCursor(16-2,1);
lcd.print(" ");
return true;
}
void startGiro(int pvel)
{
//vel = pvel;
for(; vel<pvel;vel++){
esc.write(vel);
delay(100); //
}
delay(1000);
}
void varia(int vel2)
{
for(; vel<vel2;vel++){
esc.write(vel);
delay(100); // espera o ESC apitar
}
for(; vel>vel2;vel--){
esc.write(vel);
delay(50); // espera o ESC apitar
}
}
void pisca(int n)
{
for(int i=0; i<n;i++){
digitalWrite(LED_BUILTIN,HIGH);
delay(140);
digitalWrite(LED_BUILTIN,LOW);
delay(140);
}
}
// PARAMETROS DE CICLO DEFAULT
#define NCICLOS 5;
#define TEMP_CI 10;
#define TEMP_CII 10;
#define VEL_CI 3000;
#define VEL_CII 100;
#define UNIDADE_TEMPO_MS 60000
// Pinos I2C
#define I2C_SDA A4
#define I2C_SCL A5
// Pino do ESC para o MOTOR
#define PINESC 9
// Pinos do Rotary Encoder
#define PINENC_SW 3
// Comente linha abaixo se desejar utlizar digital Pins 12 e 13 INT 0 ( Default A2 A3 INT1)
#define ANALOGPINS
#ifdef ANALOGPINS // funçao da configuração do hardware
#define PINENC_CLOCK A2
#define PINENC_DATA A3
#else
#define PINENC_CLOCK 12
#define PINENC_DATA 13
#endif
#include <Wire.h>
#include "LiquidCrystal_I2C.h" // Biblioteca para operar o LCD
#include "Arduino.h"
#include <math.h> // Biblioteca para funções matemáticas avançadas
#include "config.h"
#include "Encoder.h"
// Definições de tempo
#define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24L)
// Macros úteis para obter o tempo decorrido
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY)
// Alterar o construtor para 16x2 (substitua 0x27 pelo endereço I2C correto se necessário)
LiquidCrystal_I2C lcd(0x27, 16, 2);
char buffer[17];
String printDigits2(int digits) {
// Função utilitária para exibição de tempo digital
String returnval = "";
if (digits < 10)
returnval += "0";
returnval += digits;
return returnval;
}
String time2(int val) {
// Calcula o número de dias, horas, minutos e segundos
int days = elapsedDays(val);
int hours = numberOfHours(val);
int minutes = numberOfMinutes(val);
int seconds = numberOfSeconds(val);
// Exibição digital do tempo atual
return printDigits2(minutes) + ":" + printDigits2(seconds) + " ";
}
void displayInit(char *title1, char *title2) {
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(title1);
lcd.setCursor(0, 1);
lcd.print(title2);
delay(4000);
lcd.clear();
}
void displayInt(int linha, char *label, int valor) {
lcd.setCursor(0, linha); // Exibe as configurações no LCD
lcd.print(label);
lcd.setCursor(strlen(label) + 2, linha);
lcd.print(valor);
lcd.print(" ");
}
void displayTime(int linha, char *label, int valor) {
lcd.setCursor(0, linha); // Exibe as configurações no LCD
lcd.print(label);
lcd.setCursor(strlen(label) + 2, linha);
lcd.print(time2(valor));
lcd.print(" ");
}
void menu(char *title, char *itens[], int n) {
if (posEncoder == encoder.getPosition())
return;
posEncoder = positivando(encoder.getPosition(), n);
encoder.setPosition(posEncoder);
int selected = posEncoder % n;
Serial.println(title);
lcd.setCursor(0, 0);
lcd.print(title);
lcd.print(" ");
lcd.setCursor(0, 1);
for (int i = 0; i < n; i++) {
if (i == 0) {
lcd.print("[");
lcd.print(itens[(selected + i) % n]);
lcd.print("]");
} else {
lcd.print(" ");
lcd.print(itens[(selected + i) % n]);
lcd.print(" ");
}
}
lcd.print(" ");
}
int positivando(int valor, int n) {
while (valor < 0)
valor += n;
return valor;
}
#include <Wire.h>
#include "LiquidCrystal_I2C.h" // Biblioteca para operar o LCD
#include "Arduino.h"
#include <math.h> // Biblioteca para funções matemáticas avançadas
#include "config.h"
#include "Encoder.h"
// Definições de tempo
#define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24L)
// Macros úteis para obter o tempo decorrido
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY)
// Alterar o construtor para 16x2 (substitua 0x27 pelo endereço I2C correto se necessário)
LiquidCrystal_I2C lcd(0x27, 16, 2);
char buffer[17];
String printDigits2(int digits) {
// Função utilitária para exibição de tempo digital
String returnval = "";
if (digits < 10)
returnval += "0";
returnval += digits;
return returnval;
}
String time2(int val) {
// Calcula o número de dias, horas, minutos e segundos
int days = elapsedDays(val);
int hours = numberOfHours(val);
int minutes = numberOfMinutes(val);
int seconds = numberOfSeconds(val);
// Exibição digital do tempo atual
return printDigits2(minutes) + ":" + printDigits2(seconds) + " ";
}
void displayInit(char *title1, char *title2) {
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(title1);
lcd.setCursor(0, 1);
lcd.print(title2);
delay(4000);
lcd.clear();
}
void displayInt(int linha, char *label, int valor) {
lcd.setCursor(0, linha); // Exibe as configurações no LCD
lcd.print(label);
lcd.setCursor(strlen(label) + 2, linha);
lcd.print(valor);
lcd.print(" ");
}
void displayTime(int linha, char *label, int valor) {
lcd.setCursor(0, linha); // Exibe as configurações no LCD
lcd.print(label);
lcd.setCursor(strlen(label) + 2, linha);
lcd.print(time2(valor));
lcd.print(" ");
}
void menu(char *title, char *itens[], int n) {
if (posEncoder == encoder.getPosition())
return;
posEncoder = positivando(encoder.getPosition(), n);
encoder.setPosition(posEncoder);
int selected = posEncoder % n;
Serial.println(title);
lcd.setCursor(0, 0);
lcd.print(title);
lcd.print(" ");
lcd.setCursor(0, 1);
for (int i = 0; i < n; i++) {
if (i == 0) {
lcd.print("[");
lcd.print(itens[(selected + i) % n]);
lcd.print("]");
} else {
lcd.print(" ");
lcd.print(itens[(selected + i) % n]);
lcd.print(" ");
}
}
lcd.print(" ");
}
int positivando(int valor, int n) {
while (valor < 0)
valor += n;
return valor;
}
#include <Wire.h>
#include "LiquidCrystal_I2C.h" // Biblioteca para operar o LCD
#include "Arduino.h"
#include <math.h> // Biblioteca para funções matemáticas avançadas
#include "config.h"
#include "Encoder.h"
// Definições de tempo
#define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24L)
// Macros úteis para obter o tempo decorrido
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY)
// Alterar o construtor para 16x2 (substitua 0x27 pelo endereço I2C correto se necessário)
LiquidCrystal_I2C lcd(0x27, 16, 2);
char buffer[17];
String printDigits2(int digits) {
// Função utilitária para exibição de tempo digital
String returnval = "";
if (digits < 10)
returnval += "0";
returnval += digits;
return returnval;
}
String time2(int val) {
// Calcula o número de dias, horas, minutos e segundos
int days = elapsedDays(val);
int hours = numberOfHours(val);
int minutes = numberOfMinutes(val);
int seconds = numberOfSeconds(val);
// Exibição digital do tempo atual
return printDigits2(minutes) + ":" + printDigits2(seconds) + " ";
}
void displayInit(char *title1, char *title2) {
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(title1);
lcd.setCursor(0, 1);
lcd.print(title2);
delay(4000);
lcd.clear();
}
void displayInt(int linha, char *label, int valor) {
lcd.setCursor(0, linha); // Exibe as configurações no LCD
lcd.print(label);
lcd.setCursor(strlen(label) + 2, linha);
lcd.print(valor);
lcd.print(" ");
}
void displayTime(int linha, char *label, int valor) {
lcd.setCursor(0, linha); // Exibe as configurações no LCD
lcd.print(label);
lcd.setCursor(strlen(label) + 2, linha);
lcd.print(time2(valor));
lcd.print(" ");
}
void menu(char *title, char *itens[], int n) {
if (posEncoder == encoder.getPosition())
return;
posEncoder = positivando(encoder.getPosition(), n);
encoder.setPosition(posEncoder);
int selected = posEncoder % n;
Serial.println(title);
lcd.setCursor(0, 0);
lcd.print(title);
lcd.print(" ");
lcd.setCursor(0, 1);
for (int i = 0; i < n; i++) {
if (i == 0) {
lcd.print("[");
lcd.print(itens[(selected + i) % n]);
lcd.print("]");
} else {
lcd.print(" ");
lcd.print(itens[(selected + i) % n]);
lcd.print(" ");
}
}
lcd.print(" ");
}
int positivando(int valor, int n) {
while (valor < 0)
valor += n;
return valor;
}
#define ENCODER_MAIN
#include "config.h"
#include "Encoder.h"
#include <Arduino.h>
#ifdef ANALOGPINS
void setupRotaryEncoder()
{
// You may have to modify the next 2 lines if using other pins than A2 and A3
PCICR |= (1 << PCIE1); // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
PCMSK1 |= (1 << PCINT10) | (1 << PCINT11); // This enables the interrupt for pin 2 and 3 of Port C. a2 Clock A3 data
encoder.setPosition(0); // nao esquecer de parametrizar em RotaryEncoder encoder(A2,A3 )
pinMode(pinClick,INPUT_PULLUP);
}
// The Interrupt Service Routine for Pin Change Interrupt 1
ISR(PCINT1_vect)
{
encoder.tick(); // just call tick() to check the state.
}
#else
void setupRotaryEncoder()
{
// You may have to modify the next 2 lines if using other pins than D12 and D13
PCICR |= (1 << PCIE0); // This enables Pin Change Interrupt 0 that covers D8 a D13
PCMSK0 |= (1 << PCINT4) | (1 << PCINT5); // This enables the interrupt for pin D12 and D13 of Port .... 12 Clock 13 data
encoder.setPosition(0); // nao esquecer de parametrizar em RotaryEncoder encoder(A2,A3 ) // 12, 13);
pinMode(pinClick,INPUT_PULLUP);
}
// The Interrupt Service Routine for Pin Change Interrupt 0
ISR(PCINT0_vect)
{
encoder.tick(); // just call tick() to check the state.
}
#endif
int debounce(int pin)
{
int i;
if(digitalRead(pin)==HIGH)
return 0;
long timestart = millis();
for(i=0;digitalRead(pin) == LOW ;i++)delay(1);
if (i<3)
return 0; // menor que 3 e um ruido no canal errado
long timeend = millis();
if(timeend - timestart > 500)
return 10;
else
return 1;
}
boolean onClick(int pin)
{
if(digitalRead(pin)==HIGH)
return false;
return true;
}
#include "config.h"
void setToDefaults();
void programaEstagios();
void setHalted();
void setEnded();
void setAbortConfirmed();
boolean ciclando();
int choice(char * msg, int position0);
int choice(char * msg, int position0, int delta, int minimo, int maximo);
void testaRPM(int vel, int vel2, long tempo);
void startGiro(int pvel);
boolean onRPM(int vel2, long tempo);
float g2Rpm(float ng);
#ifdef PROCESSOS_MASTER
extern int vel;
int nciclos = NCICLOS;
int tempoH = TEMP_CI;
int velH = VEL_CI;
int velL = VEL_CII;
int tempoL = TEMP_CII;
void setToDefaults(){
nciclos = NCICLOS;
tempoH = TEMP_CI;
tempoL = TEMP_CII;
velH = VEL_CI;
velL = VEL_CII;
}
void programaEstagios()
{
nciclos = choice("Quantos Ciclos", nciclos);
velH = choice("Fase I (RPM)", velH, 100, 1000, 7200); // Seleção direta de RPM
tempoH = choice("Tempo I (em min)", tempoH);
velL = choice("Fase II (RPM)", velL, 100, 1000, 7200); // Seleção direta de RPM
tempoL = choice("Tempo II (em min)", tempoL);
lcd.setCursor(0, 1);
lcd.print("Programado, OK!");
lcd.print(" ");
delay(750);
}
void testaMotor()
{
testaRPM(117, 118, 10);
}
void setHalted(){
Serial.println("Halted");
lcd.setCursor(0,1);
lcd.print("Halted!");
lcd.print(" ");
}
void setEnded()
{
lcd.clear();
lcd.print("Terminado");
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("Clique para sair");
lcd.print(" ");
lcd.print(" ");
}
int iCiclo = 0;
void setAbortConfirmed()
{
lcd.setCursor(0,0);
lcd.print("Interrompido");
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("Clique para sair");
lcd.print(" ");
Serial.println("Interrompido");
onRPM(0,0);
iCiclo = 0;
}
int choice(char * msg, int position0)
{
encoder.setPosition(position0);
int val = encoder.getPosition();
lcd.clear(); lcd.print(msg);
lcd.setCursor(0,1); lcd.print(val);
while(!debounce(pinClick))
if(val != encoder.getPosition()){
val = encoder.getPosition();
if (val <= 0 ){
val = 1;
encoder.setPosition(val);
}
lcd.setCursor(0,1); lcd.print(val);lcd.print(" ");
}
return encoder.getPosition();
}
int choice(char * msg, int position0, int delta, int minimo, int maximo)
{
encoder.setPosition(position0/delta);
int val = encoder.getPosition();
lcd.clear(); lcd.print(msg);
lcd.setCursor(0,1); lcd.print(val*delta);
while(!debounce(pinClick))
if(val != encoder.getPosition()){
val = encoder.getPosition();
if (val < minimo ){
val = minimo;
encoder.setPosition(val);
}
if (val > maximo ){
val = maximo;
encoder.setPosition(val);
}
lcd.setCursor(0,1); lcd.print(val*delta);lcd.print(" ");
}
return encoder.getPosition()*delta;
}
boolean ciclando()
{
if(iCiclo == 0 && false){
lcd.clear(); lcd.print("Partindo ");
startGiro(150);
}
if(iCiclo++ < nciclos ){
lcd.clear(); lcd.print("Ciclo ");
lcd.print(iCiclo);
lcd.print("/");
lcd.print(nciclos);
lcd.setCursor(0, 1);
lcd.print("1 ");
lcd.print(velH); // Exibe o valor de RPM
lcd.print("x");
lcd.print(tempoH);
lcd.print(" ");
if(!onRPM(velH, tempoH)) // Usa o RPM diretamente
return false;
lcd.setCursor(0, 1);
lcd.print("2 ");
lcd.print(velL); // Exibe o valor de RPM
lcd.print("x");
lcd.print(tempoL);
lcd.print(" ");
onRPM(velL, tempoL); // Usa o RPM diretamente
return false;
}
onRPM(0, 0); // Para o motor
iCiclo = 0;
return true;
}
float g2Rpm(float ng)
{
#define R 50.
float a = (120.-30.)/(7143. - 1188.);
float b = 30 - a*1188;
float f = sqrt(ng/(1.1178620909604E-06*R));
return a*f + b;
}
#endif