Motore con sensore

Ciao a tutti,
sono nuovo nel mondo Arduino. Ho acquistato uno starter kit 2 settimane fa e poi ho deciso di cominciare a creare un piccolo rover sfruttando un vecchio modellino di auto radiocomandata smontato. Adesso il rover, una volta avviato, accelera a una velocità "x" (che è decisa da un potenzimetro) e, se incontra un ostacolo durante il percorso, grazie al sensore a infrarossi che ho installato nella parte anteriore (sharp 2Y0A21), arresta la marcia, gira le ruote anteriori, inverte la marcia per 1,5 secondi e poi riprendere a muoversi in avanti.
Il problema è che, durante la retromarcia, se ci fosse stato un ostacolo, non lo avrebbe rilevato in quanto il sensore è installato solo anteriormente. Quindi ho deciso di posizionare il sensore su di un servomotore. Adesso, quando legge un ostacolo anteriore, arresta la marcia, gira le ruote anteriori, il servomotore gira di 180° facendo in modo che il sensore legga posteriormente, e avvia la marcia all'indietro. Poi, in teoria, se ci fosse un ostacolo, dovrebbe fermarsi... ma non lo fa!

Il problema, naturalmente, era legato all'utilizzo di "delay" che non dava modo al sensore di dire ad Arduino che ci fossero ostacoli durante la marcia.
Ho provato con millis, per cercare di avere diverse letture e far decidere ad arduino se la distanza va bene oppure no. dopo svariate prove, in cui o leggeva continuamente qualcosa in retromarcia, o eseguiva tutte le righe del codice senza badare al sensore o ignorava totalmente la manovra, ho perso le speranze.

Se riuscite a darmi una mano, magari dirmi dove sbaglio, ve ne sarei grato :slight_smile:

Vi posto lo sketch prima e dopo la modifica con servomotore:

#include <Servo.h>
Servo myservo;
//
const int switchPin = 11; //pin pulsante avvio
const int motorPin = 8; // pin motore giro
int switchState = 0; //stato su "spento" del pulsante
const int potenziometro = A0;
//
const int controlPin1 = 3; //pin avanti 
const int controlPin2 = 5; //pin indietro 
int motorDirection= 1; //direzione di default 1 (avanti)
int motorEnabled = 0; //motore spento di default
//
int irpin = A1;
const int ledsensore = 6; 
//
int pos = 0;
int pos1 = 180;
//
int acc1 = 13; 
int transistor = 10; 
int acc = 4; 
int transistor2 = 2; 
int stato = 0; 
int stato2 = 0; 
//

void setup(){
  pinMode(controlPin1, OUTPUT);
  pinMode(controlPin2, OUTPUT);
  //
  pinMode(switchPin, INPUT);
  pinMode(motorPin, OUTPUT);
  pinMode(switchPin, INPUT);
  //
  pinMode(ledsensore, OUTPUT);
  pinMode(irpin, INPUT);
  myservo.attach(12);
  myservo.write(pos);
  //
  pinMode(acc1, INPUT);
  pinMode(transistor, OUTPUT);
  //
  pinMode(acc, INPUT);
  pinMode(transistor2, OUTPUT);
  
  
}

void loop(){
  byte velocita = map(analogRead(potenziometro),0,1023,0,255); //rileva velocità da potenziometro per motore 1
  switchState = digitalRead(switchPin);
  float volts = analogRead(irpin)*0.0048828125;   
  float distanza = 65*pow(volts, -1.10);
  stato = digitalRead(acc1);  
  if(switchState == HIGH){
        digitalWrite(transistor, HIGH);
        if(stato == HIGH){
          analogWrite(controlPin1, velocita);
        }
  }
  stato2 = digitalRead(acc); //transistor 2
      if(stato == HIGH){
          if(distanza < 50){ 
            digitalWrite(transistor2, HIGH); 
            if(stato2 == HIGH);               
              digitalWrite(ledsensore, HIGH);
              digitalWrite(controlPin1, LOW);
              myservo.write(pos1);
              digitalWrite(motorPin, HIGH);
              delay(1000);
              digitalWrite(controlPin2, HIGH);
              
              delay(2500);
             
              if(stato == HIGH){ 
                if(stato2 == HIGH){ 
                  if(distanza < 60){ //distanza in retromarcia
                    digitalWrite(controlPin2, LOW);
                    digitalWrite(motorPin, LOW);
                    analogWrite(controlPin1, velocita); 
                    delay(1000);
                    digitalWrite(controlPin1, LOW);
                    digitalWrite(motorPin, HIGH);
                    digitalWrite(controlPin2, HIGH);
                    delay(1500);
                    digitalWrite(motorPin, LOW);
                    digitalWrite(controlPin2, LOW);
                    myservo.write(pos);
                    delay(1500);
                    analogWrite(controlPin1, velocita);
                    digitalWrite(ledsensore, LOW);
                    digitalWrite(transistor2, LOW); // disattiva il transistor per il sensore in retromarcia
                }
               }
              
            else{
            delay(1500);
            digitalWrite(motorPin, LOW);
            digitalWrite(controlPin2, LOW);
            myservo.write(pos);
            delay(1500);
            analogWrite(controlPin1, velocita);
            digitalWrite(ledsensore, LOW);
           }
          }
      }
      }
}

e quello dopo la modifica e svariati tentativi:

#include <Servo.h>
Servo myservo;
//
const int switchPin = 11; //pin pulsante avvio
const int motorPin = 8; // pin motore giro
int switchState = 0; //stato su "spento" del pulsante
const int potenziometro = A0;
//
const int controlPin1 = 3; //pin avanti ponte H
const int controlPin2 = 5; //pin indietro ponte H
int motorDirection= 1; //direzione di default 1 (avanti)
int motorEnabled = 0; //motore spento di default
//
int irpin = A1;
const int ledsensore = 6; //led lettura valore assegnato di distanza massima
//
int pos = 0;
int pos1 = 180;
//
int acc1 = 13; //stato transistor
int transistor = 10; //attivazione transistor
int acc = 4; //stato transistor 2
int transistor2 = 2; //attivazione transistor2
int stato = 0; //stato iniziale transistor
int stato2 = 0; // stato iniziale transistor2
//
long tempo = 0;
long intervallo = 1500;

void setup(){
  pinMode(controlPin1, OUTPUT);
  pinMode(controlPin2, OUTPUT);
  //
  pinMode(switchPin, INPUT);
  pinMode(motorPin, OUTPUT);
  pinMode(switchPin, INPUT);
  //
  pinMode(ledsensore, OUTPUT);
  pinMode(irpin, INPUT);
  myservo.attach(12);
  myservo.write(pos);
  //
  pinMode(acc1, INPUT);
  pinMode(transistor, OUTPUT);
  //
  pinMode(acc, INPUT);
  pinMode(transistor2, OUTPUT);
  
  Serial.begin(9600);
  
  //time = millis();
  //letturasensore_time=millis();
}

void loop(){
  
  //time = millis();
  
  byte velocita = map(analogRead(potenziometro),0,1023,0,255); //rileva velocità da potenziometro per motore 1
  switchState = digitalRead(switchPin);
  float volts = analogRead(irpin)*0.0048828125;  
  float distanza = 65*pow(volts, -1.10);
  stato = digitalRead(acc1);  
  if(switchState == HIGH){
        digitalWrite(transistor, HIGH);
        if(stato == HIGH){
          analogWrite(controlPin1, velocita);
        }
  }
  
  stato2 = digitalRead(acc); //transistor 2
      if(stato == HIGH){
          if(distanza < 50){ 
            Serial.println("1:");
            Serial.println(distanza);
            digitalWrite(transistor2, HIGH); //attiva il transistor per il sensore in retromarcia
            if(stato2 == HIGH){               // se il transistor è arrivo, prosegue
            
              digitalWrite(ledsensore, HIGH);
              digitalWrite(controlPin1, LOW);
              myservo.write(pos1);
              digitalWrite(motorPin, HIGH);
              delay(1000);
              digitalWrite(controlPin2, HIGH);
              
              unsigned long tempo2 = millis();
              
             if(tempo2 - tempo < intervallo){
               
              if(stato == HIGH){ 
                if(stato2 == HIGH){ 
                
                  if(distanza < 60){ //distanza in retromarcia
                  tempo = tempo2;
                    Serial.println("2");
                    Serial.println(distanza); /
                    digitalWrite(controlPin2, LOW);
                    digitalWrite(motorPin, LOW);
                    analogWrite(controlPin1, velocita); 
                    delay(1000);
                    digitalWrite(controlPin1, LOW);
                    digitalWrite(motorPin, HIGH);
                    digitalWrite(controlPin2, HIGH);
                    delay(1500);
                    digitalWrite(motorPin, LOW);
                    digitalWrite(controlPin2, LOW);
                    myservo.write(pos);
                    delay(1500);
                    analogWrite(controlPin1, velocita);
                    digitalWrite(ledsensore, LOW);
             
          
            
              digitalWrite(motorPin, LOW);
              digitalWrite(controlPin2, LOW);
              myservo.write(pos);
              delay(1500);
              analogWrite(controlPin1, velocita);
              digitalWrite(ledsensore, LOW);
            }
                }
              }
             }
            }

            
      }
      }
}

oddio che macello.

Iniza a creare le funzioni:

avanti()
indietro()
ferma()
distanza(int posizione servo)

e a questo punto riscrivi il codice di conseguenza.

Prima di pubblicare il codice, nell'IDE usa la funzione "formattazione automatica" dal menù strumenti.
Diventa più leggibile. :grin:

scusate :slight_smile: ho riscritto il codice in modo che si capisca meglio...

questa è la versione sulla quale sto lavorando adesso, quella migliore diciamo. come potete vedere ho commentato dove c'è bisogno di aiuto. il problema è nel delay, ho provato alcune combinazioni anche con il millis, ma non credo di aver compreso a pieno il funzionamento... potete suggerirmi una qualche soluzione?

#include <Servo.h>
Servo servo;

const int pulsante = 11;
const int motoregiro = 8;
int statopulsante = 0;
const int potenziometro = A0;

const int avanti = 3;
const int indietro = 5;

int ir = A1;
const int ledsensore = 6;

int posservo = 0;
int posservo2 = 180;

int trans1 = 13;
int transi1 = 10;
int trans2 = 4;
int transi2 = 2;
int statotran1 = 0;
int statotran2 = 0;

void setup (){
  pinMode(avanti, OUTPUT);
  pinMode(indietro, OUTPUT);
  pinMode(pulsante, INPUT);
  pinMode(motoregiro, OUTPUT);
  pinMode(ledsensore, OUTPUT);
  pinMode(ir, INPUT);
  servo.attach(12);
  servo.write(posservo);
  pinMode(trans1, INPUT);
  pinMode(transi1, OUTPUT);
  pinMode(trans2, INPUT);
  pinMode(transi2, OUTPUT);
  
}

void loop(){
  byte velocita = map(analogRead(potenziometro),0,1023,0,255);
  statopulsante = digitalRead(pulsante);
  float volt = analogRead(ir)*0.0048828125;
  float distanza = 65*pow(volt, -1.10);
  statotran1 = digitalRead(trans1);
  if(statopulsante == HIGH){
    digitalWrite(transi1, HIGH);
    if(statotran1 == HIGH){
      analogWrite(avanti, velocita);
    }
  }
  statotran2 = digitalRead(trans2);
  if(statotran1 == HIGH){
    if(distanza < 50){
      digitalWrite(transi2, HIGH);
      if(statotran2, HIGH);
      digitalWrite(ledsensore, HIGH);
      digitalWrite(avanti, LOW);
      servo.write(posservo2); //il servo punta l'IR verso il lato posteriore per la retromarcia
      digitalWrite(motoregiro, HIGH);
      delay(1000);
      digitalWrite(indietro, HIGH); //qui avvio la retromarcia, durante il quale l'IR deve vedere cosa c'è dietro.
      delay(2500); //ma il delay blocca il programma per 2,5 secondi, così l'if seguente viene eseguita solo se nell'istante subito dopo il delay c'è qualcosa.
      if(statotran1 == HIGH){
        if(statotran2 == HIGH){
          if(distanza < 60){ // in retromarcia, se vede l'IR vede qualcosa, esegue l'if
            digitalWrite(indietro, LOW);
            digitalWrite(motoregiro, LOW);
            analogWrite(avanti, velocita);
            delay(1000);
            digitalWrite(avanti, LOW);
            digitalWrite(motoregiro, HIGH);
            digitalWrite(indietro, HIGH);
            delay(1500);
            digitalWrite(motoregiro, LOW);
            digitalWrite(indietro, LOW);
            servo.write(posservo);
            delay(1500);
            analogWrite(avanti, velocita);
            digitalWrite(ledsensore, LOW);
          }
        }
      }
      else{ //se l'IR non vede niente, esegue l'else
        delay(1500);
        digitalWrite(motoregiro, LOW);
        digitalWrite(indietro, LOW);
        servo.write(posservo);
        delay(1500);
        analogWrite(avanti, velocita);
        digitalWrite(ledsensore, LOW);
      }
    }
  }
}

secondo me il problema è che dopo le delay non fai più analogRead di distanza, e quindo usi il vecchio valore.

si ma quello è statico, prima di premere il pulsante di avvio devo impostare, tramite potenziometro, la velocità che poi sarà utilizzata.
Il problema è un altro. Durante l' "indietro", arduino dovrebbe continuare a leggere i dati provenienti dall'IR e, nel caso ci fosse un ostacolo, fermare la marcia indietro ed eseguire l'if corrispondente. il problema è questo: come conteggio 2,5 secondi di marcia indietro durante il quale arduino dovrebbe continuare a leggere dall'IR ed eseguire le operazioni contenute nell'if, nel caso di lettura positiva?
non so se mi sono spiegato bene ... :slight_smile:

con la millis() ottieni il numero di miullisecondi trascorsi da quando arduino è acceso... una millis() ora e una tra un pò mi dice quanto tempo è trascorso, con una banale sottrazione, no?

forse ho capito come usarlo... il mio problema è che il funzionamento lo capisco, ma non riesco ad applicarlo nel codice. provo e vi faccio sapere :slight_smile:

sto impazzendo con sto millis. da quello che ho capito, tu puoi prendere il tempo in due punti e sapere quanto tempo è trascorso tra questi 2 valori. ma come faccio ad effettuare un conteggio? devono passare 2500 millisecondi, ognuno dei quali arduino deve leggere il sensore IR e, se soddisfa l'if(distanza < 60), procedere.

dunue, tu vuoi avanzare per 2500ms salvo ostacoli. la delay "blocca" l'esecuzione del codice non permettendoti la misura.

Ma come funziona la delay? semplice!

void delay(unsigned long delay){
  unsigned long inizio = millis();
  while (millis()-inizio < delay){ //finhcè non scade il delay
    //fai nulla
  }
}

ma cavoli! a questo punto è facile scrivere una TUA delay, che anzichè fare niente, controla la distanza dell'ostacolo, e in caso sia al di sotto di una soglia interrompe tutto!!

void delayAntiUrto(unsigned long delay, int distanzaMinima){
  unsigned long inizio = millis();
  while (millis()-inizio < delay && leggiDistanza() > distanzaMinima){ //finchè c'è da aspettare e il muro è lontano
    //fai nulla
  }
}

ps. e usa queste benedette funzioni! impara ad usarle, se non sai falro, o da quest progetto non ne esci più! vedi come anzichè riscrvere queste 3 righe mille volte puoi chiamare solo la funzione. Se un domani compri un altro sensore, o trovi un errore, modificherai solo queste tre righe et voilà, senza funzioni.......... auguri

ok, imparerò ad usare le funzioni, non sapevo di questo metodo di programmazione... anche perchè programmo da 2 settimane :smiley:

Comunque , se provo a richiamare la seconda funzione che hai scritto, mi dice "too few arguments to function 'void delayAntiUrto(long unsigned int, int)'"

pochi argomenti?

ok niente, sono un nabbo... ho capito perchè lo dice :slight_smile: il fatto è che devo comprendere bene come utilizzare le funzioni...

mmm bene, sono arrivato a questo punto. la funzione la faccio eseguire nel punto interessato del programma. da quello che ho capito del ciclo while, quando l'istruzione tra parentesi risulta falsa, esce dal ciclo while e continua con il programma. bene, in teoria se trova un muro e la distanzaMinima (che, mettiamo caso, sia 60) diventa 30, dovrebbe uscire da while ed eseguire l'if successivo. non lo fa perchè la distanza letta è sempre la stessa, quella iniziale...

void delayAntiUrto(unsigned long delay, int distanzaMinima){
  unsigned long inizio = millis();
  float volt = analogRead(ir)*0.0048828125;
  float distanza = 65*pow(volt, -1.10);
  while (millis()-inizio < delay && distanza > distanzaMinima){ 
    Serial.println("Distanza durante");
    Serial.println(distanzaMinima);
    Serial.println(distanza);
  }
  if(distanza < distanzaMinima){
    manovraevasiva();
    Serial.println("Distanza manovra evasiva:");
    Serial.println(distanza);

  }

}

Ciao a tutti, volevo sapere come si fa a controllare la velocità di un motore.
Ho scritto il programma, e fintanto che agisce una bassa tensione, il mio motore reagisce al programma diminuendo la sua velocità, appena collego il mio motore da 12v e 250w alla batteria da 12v , questo non mi risponde più.
Volevo chiedere se devo collegarci dei condensatori, perché ho visto che il mio primo motore c'è li aveva.
Grazie in anticipo

Dipende dal tipo di motore, dipende dal driver che deve essere collegati, dipende dal tipo di controllo che vuoi avere sul motore.
Hai detto che lo vuoi controllare in velocità, ma che tipo di motore è e come l'hai collegato? foto? schema? datasheet?