banner

Ir para o Forum

Câmera robô controlada com ESP32


Mais um projeto de mecatrônica aqui hoje: uma câmera robô controlada com ESP32. Vou te apresentar um código multi task de controle físico de motor de passo com posicionamento em tempo real e mostrar o seu funcionamento em um Slider.
Aqui neste vídeo quero te mostrar como você move a câmera e como é o software que vai no ESP32. Portanto, não falo da parte mecânica, mas deixo o projeto logo abaixo para você fazer o download.




Demonstração





Recursos usados para construção da eletrônica

·         1 Esp32 LoRa com display OLED
·         1 Drivers DRV8825
·         1 motores de passo Nema 17
·         2 chaves de fim de curso ópticas
·         3 botões push
·         3 resistores 10k ohm
·         Jumpers para conexão
·         Protoboard
·         Fonte 12V





Montagem da eletrônica






Código

Includes e variáveis


#include <Arduino.h> //Importa as funções do arduino
#include <Wire.h>  //Necessário apenas para o Arduino 1.6.5 e posterior
#include <SSD1306.h> //O mesmo que #include "SSD1306Wire.h"
#include <SPI.h> //Lib de comunicação SPI

//OLED_SDA -- GPIO4
//OLED_SCL -- GPIO15
//OLED_RST -- GPIO16

#define SDA    4
#define SCL   15
#define RST   16

//Instanciando e ajustando os pinos do objeto "display"
SSD1306  display( 0x3c, SDA, SCL,RST); 

const int ENA = 23; //Pino "enable" - DRV8825
const int DIR = 22; //Pino "direction" - DRV8825
const int STP = 17; //Pino "step" - DRV8825
const int EMAX = 37; //Pino do fim de curso máximo
const int EMIN = 36; //Pino do fim de curso mínimo
double SPM = 400.0; //Passo por milimetro
bool LVL = LOW; //Nível de ativacao da chave (alto ou baixo)
int ACC; //Aceleração
double MIN_SPEED; //Velocidade mínima
double MAX_SPEED; //Velocidade máxima
static double Absolute = 0; //variável que guarda a posição do motor

const int BtBackPin = 12; //Pino do botão trás
const int BtHomePin = 33; //Pino do botão home
const int BtFowardPin = 13; //Pino do botão frente

//Variáveis que guardam a leitura dos botões para usar em ambas as tasks
int ButtonBack=0; 
int ButtonHome=0;
int ButtonFoward = 0;


Função Setup e loop


void setup(){

  Serial.begin(115200);//Apenas para debug

  pinMode(ENA, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(STP, OUTPUT);
  pinMode(EMAX, INPUT);
  pinMode(EMIN, INPUT);
  pinMode(BtBackPin,INPUT);
  pinMode(BtHomePin,INPUT);
  pinMode(BtFowardPin,INPUT);

  //Configuração de movimento
  motionConfig(200, 50, 5);

  //Criamos a task que gerencia o display OLED e os botões físicos
  xTaskCreatePinnedToCore(Task_display, "Task_display", 10000, NULL, 1, NULL, 0); 
  Serial.println("task display - ONLINE");

  //Criamos a task responsável pelo movimento do motor
  xTaskCreatePinnedToCore(Task_motion, "Task_motion", 10000, NULL, 2, NULL, 1); 
  Serial.println("task motion - ONLINE");
  
}

void loop(){
  //loop vazio
}


Funções básicas de movimento (Importado da biblioteca de motor de passo)


//Configura aceleração, velocidade máxima e velocidade mínima
void motionConfig(double acceleration, double maxSpeed, double minSpeed) {

  ACC = acceleration * SPM;
  MAX_SPEED = maxSpeed * SPM;

  if (minSpeed > maxSpeed)
    MIN_SPEED = maxSpeed * SPM;
  else
    MIN_SPEED = minSpeed * SPM;
}

//Le as chaves de fim de curso
bool eRead(int pin) {

  if (LVL && digitalRead(pin)) {
    return true;
  }
  if (!LVL && !digitalRead(pin)) {
    return true;
  }
  return false;
}

//Verifica o movimento do motor
bool canGo(bool direction) {

  if (direction && eRead(EMAX))
    return false;
  if (!direction && eRead(EMIN))
    return false;
  return true;
}

//Gera o pulso do motor
void motorMove(double period, bool direction) {

  digitalWrite(DIR, direction);
  if (canGo(direction)) {
    digitalWrite(STP, HIGH);
    delayMicroseconds(int(period) / 2);
    digitalWrite(STP, LOW);
    delayMicroseconds(int(period) / 2);
  }
  else {
    delayMicroseconds(period);
  }
}

//Movimenta o motor em modo relativo
void motorMoveTo(double distance, bool direction) {


  double MIN_SPEED_PERIOD = 1.0 / MIN_SPEED;
  double MAX_SPEED_PERIOD = 1.0 / MAX_SPEED;
  double ACC_SPEED_PERIOD = MIN_SPEED_PERIOD;
  unsigned long PATH_STEPS = distance * SPM;
  long STEPS_TO_STOP = PATH_STEPS / 2;
  double MAX_SPEED_REACHED;
  bool flag = true;

  for (long int i = 0; i < PATH_STEPS; i++) {

    if (i < (PATH_STEPS / 2)) {

      if (ACC_SPEED_PERIOD > MAX_SPEED_PERIOD) {

        ACC_SPEED_PERIOD = 1.0 / sqrt((MIN_SPEED * MIN_SPEED) + (2.0 * ACC * i));
        motorMove(1000000 * ACC_SPEED_PERIOD, direction);
        
        MAX_SPEED_REACHED = (1.0 / ACC_SPEED_PERIOD);
        
      }
      else
      {
        
        if (flag) {
          STEPS_TO_STOP = i;
          MAX_SPEED_REACHED = MAX_SPEED;
          flag = false;
        }
        motorMove(1000000 * MAX_SPEED_PERIOD, direction);
        
      }
    }
    else{
      if (i > PATH_STEPS - STEPS_TO_STOP) {

        ACC_SPEED_PERIOD = 1.0 / sqrt((MAX_SPEED_REACHED * MAX_SPEED_REACHED) + 2.0 * (ACC * -1.0) * (i - (PATH_STEPS - STEPS_TO_STOP)));
        
        motorMove(1000000 * ACC_SPEED_PERIOD, direction);
        
      }
      else
      {
        
        motorMove(1000000 * MAX_SPEED_PERIOD, direction);
        
      }
    }
  }
}


Novas funções de movimento


//Movimenta o motor em modo absoluto
void MoveAbsolute(double coordinate){
  double position;

  
  if(coordinate!=Absolute){
    position = coordinate-Absolute;
    if(position<0){
      motorMoveTo((position*(-1.0)),LOW);
    }
    else{
      motorMoveTo(position,HIGH);
    }
    Absolute=Absolute+position;
  }
  
}

//Zera a posição do motor
void HomeAxis(){

  double SPEED_PERIOD = 1000000*(1.0 / (MAX_SPEED/2));//Metade da velocidade máxima

  while(digitalRead(EMIN)){
    motorMove(SPEED_PERIOD,LOW); 
  }

  Absolute=0;
  delay(250);
  MoveAbsolute(5);
  delay(250);

  while(digitalRead(EMIN)){
    motorMove(SPEED_PERIOD*3,LOW); // 1/3 da velocidade máxima (período 3 vezes maior)
  }
  Absolute=0;
}


Criação das Tasks

//Task que gerencia o display OLED e os botões físicos
void Task_display(void *p){

  //Inicia o display
  display.init();

  //Vira a tela verticalmente
  display.flipScreenVertically();

  //ajusta o alinhamento para a esquerda
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  //ajusta a fonte para Arial 16
  display.setFont(ArialMT_Plain_16);

  //Liga o display
  display.displayOn();

  //Limpa o display
  display.clear();

  TickType_t Taskdelay = 1 / portTICK_PERIOD_MS;  

  while(true)
  {
    //Lê os botões de movimento
    ButtonBack = digitalRead(BtBackPin);
    ButtonHome = digitalRead(BtHomePin);
    ButtonFoward = digitalRead(BtFowardPin);

    //escreve no display a posião atual do motor
    display.clear();
    display.drawString(0,0,"Posição:");
    display.drawString(0, 28, String(Absolute,4));
    display.drawString(67, 28, "mm");
    display.display();

    //delay que reinicia o WatchDog
    vTaskDelay(Taskdelay);
  }
}

//Task responsável pelo movimento do motor através dos botões
void Task_motion(void *p){
  
  while(true)
  {
    if(ButtonBack){
      motorMove(50,LOW);
      if(canGo(LOW)){
        Absolute = Absolute - (1.0/400.0);
      }
    }
    else{

      if(ButtonFoward){
        motorMove(50,HIGH);
        if(canGo(HIGH)){
          Absolute = Absolute + (1.0/400.0);
        }
      }
      else{
        if(ButtonHome){
          HomeAxis();
        }
      }
    }    
  }
}



Faça o download dos arquivos:

PDF

INO

Projeto




4 comentários:

  1. fascinante prataforma de suporte que vc realiza de boa vontade generosa parabens Fernando k eu precisava muito desse suporte Obrigado Fernando K

    ResponderExcluir
  2. fascinante prataforma de suporte que vc realiza de boa vontade generosa parabens Fernando k eu precisava muito desse suporte Obrigado Fernando K

    ResponderExcluir
  3. Quando será lançado o curso que você esta fazendo?

    ResponderExcluir
  4. Caraka Fernandao!! Estava começando a pensar em montar um... e como que se caísse do céu... Maravilha!!

    Fui na Campus Party BR12, esperava ter lhe encontrado lá... encontrei o pessoal do Arduino Brasil, Brincando com Ideias... até o mito Newton Braga esteve lá... vlw pelos excelentes projetos... Uma hora ensina a fazer uma losa dessa ai. kkk!

    ResponderExcluir

Tecnologia do Blogger.