Motor de passos + driver (código para girar em graus)

Bom dia galera, testei um monte de códigos no meu motor de passos e não to conseguindo fazer ele rodar em graus, conforme eu preciso, gostaria de fazer ele girar 360 graus e parar.

Alguém teria algum exemplo ou código funcionando pra mim poder usar e fazer alguns testes aqui?

comprei esse motor aqui, aqui mesmo no DX:

28YBT-48 Stepper Motor with ULN2003 Driver (DC 5V)

valeu

de quantos passos é o motor???

onde é que os códigos falham?

Quantos passos você esta dando para ter 360? Pela especificação, se entendi, você deve fazer esse cálculo: 360/(5,625*1/64) = 4096

Pois cada passo é (5,625*1/64) = 0,087890625 de 360 graus. então você precisa de 4096 passos para 360 graus.

Ah, sim, e esse motor não é 28YBT-48, mas sim 28YBJ-48 :wink:

Acabei chegando nesse código aqui, consigo através da variavel Steps2Take = 2048 dar uma volta completa, 1024 da meia volta, 4096 duas voltas e por ai vai... só fiquei meio na duvida sobre o que realmente faz as variaveis STEPS e setSpeed, o STEPS se for muito alta nao roda o motor e o setSpeed na verdade só gostaria de saber até que valor posso botar.. se botar muito alto nao roda tb.. 300 é meio um valor máximo pro meu motor como notei nos testes que fiz.. mas enfim, com esse código ja vou conseguir fazer o que eu pretendo :slight_smile:

abraço

#include <Stepper.h>

#define STEPS  100

Stepper small_stepper(STEPS, 8, 10, 9, 11);
int  Steps2Take;

void setup() {
  small_stepper.setSpeed(300);  
}

void loop() {
  Steps2Take  =  2048;
  small_stepper.step(Steps2Take);
  delay(1000);
}

Como você esta usando a propriedade de uma livraria, somente ela pode te dizer :wink:

Abra o arquivo Stepper.cpp da livraria, verá que a velocidade é determinada pela função abaixo:

void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L / this->number_of_steps / whatSpeed;
}

O que ocorre, quando você coloca velocidade de 300, é que o tempo (step_delay) entre o "chaveamento" do pólos é muito curto para mover o eixo.

Não tenho esses valores, mas creio que testando (como você já fez) seja a melhor forma de você encontrar os valores máximos para o teu motor.

Uma coisa que você pode tentar é iniciar o motor com menor "velocidade" e ir aumentando gradativamente, até que você encontre o limite.

Só lembre-se no futuro que o arduino "para" enquanto a função small_stepper.step(Steps2Take); esta dando os passos. :wink:

void Stepper::step(int steps_to_move)
{  
  int steps_left = abs(steps_to_move);  // how many steps to take
  
  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) {this->direction = 1;}
  if (steps_to_move < 0) {this->direction = 0;}
    
    
  // decrement the number of steps, moving one step each time:
  while(steps_left > 0) {

edit1: lembrei deste post: Problema com motor de passo. - #11 by Mortis - Português - Arduino Forum

opa, valeu pelas explicações.. to com outra dúvida.. vou postar o código todo aqui..

eu gostaria de digitar um valor, e só qndo esse valor fosse digitado rodasse a função loop.. pelos print que botei.. ele fica no loop e nao para ali no serial.read.. acho que ia parar e ficar na linha até que fosse digitado o valor, se sem digitar nada ele ta passando igual e imprimindo sempre -1 na variavel digValue, sendo que eu atribuo 0 pra ela, e qndo digito algo no terminal ela imprime um valor 49.. sei la que lixo ou o que ela ta pegando pra imprimir, mas gostaria de conseguir controlar isso, com uma opcao entrar ou nao ali no if certo dai. Alguma dica?

#include <Ultrasonic.h>
#include <Stepper.h>

#define passos  100
#define echoPin 6 //Pino 6 recebe o pulso do echo
#define trigPin 5 //Pino 5 envia o pulso para gerar o echo

Ultrasonic ultrasonic(5,6);


Stepper small_stepper(passos, 8, 10, 9, 11);

int  qtdDeVoltas;

void setup()   
{ 
  Serial.begin(9600); //inicia a porta serial
  pinMode(echoPin, INPUT); // define o pino 6 como entrada (recebe)
  pinMode(trigPin, OUTPUT); // define o pino 5 como saida (envia)
  small_stepper.setSpeed(300);  
}

void loop() 
{
  int digValue = 0;
 
  digValue = Serial.read();
  int x = verifica_distancia();
  Serial.println(digValue);
  
  if(digValue == 1){
    Serial.println("entrouu available");
    if(x == 1){
      qtdDeVoltas  =  1024; //1024 para uma volta completa
      small_stepper.step(qtdDeVoltas);
    }  
  }
}


int verifica_distancia(){
  
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);

    int distancia = (ultrasonic.Ranging(CM));

    Serial.print("Distancia em CM: ");
    Serial.println(distancia);
    delay(1000);
    
    if(distancia > 10){
      return 1;
    }
    else if(distancia < 10){
      return 0;
    }
    
}

Tu estás a usar ASCII quando envias algo pela porta série.

Então se vires aqui http://www.asciitable.com/, vês o valor inteiro que o símbolo que envias pela porta série equivale.

Ao fazeres isto:

  int digValue = 0;

Estás a dizer que essa variável vai ser usada como um inteiro e não como um caracter (que é o que estás a fazer).

Então faz isto, troca o tipo dessa variável de int para char.

Depois aqui:

  if(digValue == 1){
    Serial.println("entrouu available");
    if(x == 1){
      qtdDeVoltas  =  1024; //1024 para uma volta completa
      small_stepper.step(qtdDeVoltas);
    }  
  }

Em vez de veres se é igual a 1 (nota que 1 é o código "SOH" e não '1'), compara com '1' assim:

  if(digValue == '1'){
    Serial.println("entrou available");
    if(x == 1){
      qtdDeVoltas  =  1024; //1024 para uma volta completa
      small_stepper.step(qtdDeVoltas);
    }  
  }

Para bloqueares o código, com a porta série tens de usar o método available.

while(Serial.available() == 0); //enquanto não receber nada na porta série... fica aqui empancado.

Por último, acho que devias estudar um pouco mais protocolos. Eu meti uns posts (muito incompletos até agora) a falar de protocolos e pelo menos esta parte do ASCII já está coberta.

Deiwys,

Além das orientações que o bubulindo te passou, sugiro que use

if (Serial.available() > 0) {
}

que indica se tem algo para ler na serial.

Quando usas digValue = Serial.read(); já estas a tirar um char da porta (mas se não tem char, o que pode-se tirar? ^^), por isso teu programa imprime -1 (quantidade de char na porta). E ele imprime -1 a cada loop, porque não existe condição para que ele não o faça, então veja o código "ajeitado" abaixo:

void loop() 
{
  //Com esse if só faz algo se tiver "algo" na serial
  if (Serial.available() > 0) {
    char digValue = Serial.read();
    int x = verifica_distancia();
    Serial.println(digValue);
    
    if(digValue == 1){
      Serial.println("entrouu available");
      if(x == 1){
        qtdDeVoltas  =  1024; //1024 para uma volta completa
        small_stepper.step(qtdDeVoltas);
      }  
    }
  }
}

bubulindo:
(...)Eu meti uns posts (muito incompletos até agora) a falar de protocolos e pelo menos esta parte do ASCII já está coberta.

Mas acho que ele terá de esperar uma das partes mais importante dos teus posts, ou onde o povo parece ter mais dúvidas, And this is where the problem starts... should we send it in binary or ASCII?

Mortis:
Mas acho que ele terá de esperar uma das partes mais importante dos teus posts, ou onde o povo parece ter mais dúvidas, And this is where the problem starts... should we send it in binary or ASCII?

Ups... Tenho de voltar a isso.
O problema é que não existe uma resposta correcta para essa questão.

bubulindo:
Ups... Tenho de voltar a isso.
O problema é que não existe uma resposta correcta para essa questão.

Existe sim!!! "Depende" rs

O negócio é postar exemplos de cada método, então o leitor escolherá o que melhor cabe! :wink:

Sim, depende...
Mas quem for usar binário, certamente que não precisa de ler num blog sobre como fazer. Mas não deixa de ser interessante, se calhar deixar já isso patente e de lado e focar-me em protocolos em ASCII.

Opa, valeu mais uma vez bubulindo e Mortis. Eu tinha realmente tentado usar esse avaliable() pra tentar 'parar' o código, mas não tinha dado certo.. mas vou tentar novamente.. e vou fazer as modificações que me orientaram.. Obrigado.

Abraço.

bubulindo:
(...)Mas quem for usar binário, certamente que não precisa de ler num blog sobre como fazer.(...)

Também depende lol (eu tinha dificuldades para enxergar o uso de binários, mas era-me muito simples com ascii rs)

Deiwys:
Opa, valeu mais uma vez bubulindo e Mortis. Eu tinha realmente tentado usar esse avaliable() pra tentar 'parar' o código, mas não tinha dado certo.. mas vou tentar novamente.. e vou fazer as modificações que me orientaram.. Obrigado.

Abraço.

Estamos aqui para ajudar, diga-nos se funcionou como esperado.

Normalmente e tendo atenção ao computador em causa e como é enviado, usar binário é o melhor para enviar dados numéricos... não há cá conversões de strings nem nada do género. Mesmo em binário há formas de enviar o mesmo conteúdo em menos espaço com menos poder de computação.

Mas encalha-se sempre no mesmo problema... se não se estiver a fazer o software do computador, não dá mesmo para ser simples. Vou tentar deixar isso patente no próximo post.

bubulindo:
(...)não há cá conversões de strings nem nada do género. Mesmo em binário há formas de enviar o mesmo conteúdo em menos espaço com menos poder de computação.(...)

menos espaço e menos poder de computação foram pontos que me levaram a adotar binários em uma aplicação.

bubulindo:
Mas encalha-se sempre no mesmo problema... se não se estiver a fazer o software do computador, não dá mesmo para ser simples. Vou tentar deixar isso patente no próximo post.

bacana! aguardando para ler =)

eu gostaria de digitar um valor, e só qndo esse valor fosse digitado rodasse a função loop.. pelos print que botei.. ele fica no loop e nao para ali no serial.read.. acho que ia parar e ficar na linha até que fosse digitado o valor, se sem digitar nada ele ta passando igual e imprimindo sempre -1 na variavel digValue, sendo que eu atribuo 0 pra ela, e qndo digito algo no terminal ela imprime um valor 49.. sei la que lixo ou o que ela ta pegando pra imprimir, mas gostaria de conseguir controlar isso, com uma opcao entrar ou nao ali no if certo dai. Alguma dica?

while (Serial.available() > 0) { Serial.read(); } // limpa o 'lixo'

while (Serial.available() == 0); // fica parado aqui enquanto é zero
digValue = Serial.read(); // le quando digitado

isso que quer?
Só um adendo: cuidado com esses loops que 'travam' o código, se programados de maneira errada...vai travar seu código!