HC-SR04 : lettura infinita

Buongiorno a tutti!
volevo porvi alcuni quesiti:
-il codice che posterò controlla una base mobile (4 ruote)
-effettua ad ogni comando una lettura di distanza con un HC-SR04
la mia domanda è: riesco a fargli leggere la distanza con l'ostacolo ogni secondo per esempio?

Questo è il mio codice:

#include <NewPing.h>
#include <AFMotor.h>
#include <Servo.h>
#include <SoftwareSerial.h>

#define PingPin A0
NewPing sonar(PingPin,PingPin);

const int speed = 20; //velocità in %
#define RX 15  //A1
#define TX 16 //A2
#define Led 17 //A3 
#define FotoR 18//A4
int data;
int data2;
Servo servo; 
AF_DCMotor Motor_Left_Front(4,MOTOR34_1KHZ);
AF_DCMotor Motor_Right_Front(3,MOTOR34_1KHZ);
AF_DCMotor Motor_Left_Rear(1,MOTOR12_1KHZ);
AF_DCMotor Motor_Right_Rear(2,MOTOR12_1KHZ);
SoftwareSerial btSerial(RX,TX);
void setup() {
  Serial.begin(9600);
  btSerial.begin(9600);
  servo.attach(9);
  servo.write(45);
  pinMode(Led,OUTPUT);
  pinMode(FotoR,INPUT);
  Motor_Left_Front.setSpeed(255);
  Motor_Right_Front.setSpeed(255);
  Motor_Left_Rear.setSpeed(255);
  Motor_Right_Rear.setSpeed(255);
}

void loop() {
   
if(btSerial.available())
  {
    data2=btSerial.read();
    Serial.print(data2);
    //data=Serial.read();
    Serial.print(data2, HEX);
    Serial.print(" - ");
    Serial.println((char) data2);
    switch(data2)
     {
      
      case '0'://Reset servo position
      servo.write(45);
      break;
      
      case '1'://Look right
      servo.write(90);
      break;
      
      case '2'://Look left
      servo.write(-90);
      break;

      case '3': //ServoMotor and Distance (HC-SR04)
      ServoRotation();
      break;

      case 'D': //Distance (HC-SR04)
      Distance();
      break;
      
      case 'O': //Led OFF
      btSerial.print("Led OFF");
      btSerial.print("");
      digitalWrite(Led,LOW);
      break;

      case 'N': //Led ON
      btSerial.print("Led ON");
      btSerial.print("");
      digitalWrite(Led,HIGH);
      break;
      
      case 'F': //Forward
      btSerial.print("FORWARD");
      btSerial.print("");
      Motor_Left_Front.run(FORWARD);
      Motor_Right_Front.run(FORWARD);
      Motor_Left_Rear.run(FORWARD);
      Motor_Right_Rear.run(FORWARD);
      ServoRotation();
      break;

       case 'B': //Backward
       btSerial.print("BACKWARD");
       btSerial.print("");
       Motor_Left_Front.run(BACKWARD);
       Motor_Right_Front.run(BACKWARD);
       Motor_Left_Rear.run(BACKWARD);
       Motor_Right_Rear.run(BACKWARD);
       break;

       case 'S': //Stop
       btSerial.print("STOP");
       btSerial.print("");
       Motor_Left_Front.run(RELEASE);
       Motor_Right_Front.run(RELEASE);
       Motor_Left_Rear.run(RELEASE);
       Motor_Right_Rear.run(RELEASE); 
       break;

       case 'R': //Turn Right 
       btSerial.print("Turn Right");
       btSerial.print("");
       Motor_Left_Front.run(BACKWARD);
       Motor_Right_Front.run(BACKWARD);
       Motor_Left_Rear.run(RELEASE);
       Motor_Right_Rear.run(BACKWARD );
       break;
       
       case 'L': //Turn Left
       btSerial.print("Turn Left");
       btSerial.print("");
       Motor_Left_Front.run(BACKWARD);
       Motor_Right_Front.run(BACKWARD);
       Motor_Left_Rear.run(BACKWARD);
       Motor_Right_Rear.run(RELEASE );
       break;

       case 'A': //Auto light
       Light();
       break;
      }
  }
  }


void ServoRotation()
{
     //senso orario
     servo.write(0);
     delay(300);
     servo.write(45);
     Distance();
     delay(300);
     servo.write(90);
     delay(300);
     //anti-orario
     servo.write(135);
     delay(300);
     servo.write(90);
     delay(300);
     servo.write(45);
     Distance();
     delay(300);
}

void Distance()
{
  delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay

  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).

  btSerial.print("Distance: ");
  btSerial.print(uS/US_ROUNDTRIP_CM); // convert time into distance
  
  btSerial.println("cm"); 
  btSerial.print("");
  if(uS/US_ROUNDTRIP_CM<10)
  {
       Motor_Left_Front.run(RELEASE);
       Motor_Right_Front.run(RELEASE);
       Motor_Left_Rear.run(RELEASE);
       Motor_Right_Rear.run(RELEASE); 
    }
}


void Light()
{
  int luce=analogRead(FotoR);
  btSerial.println("Light: "+ String(luce));
  if(luce<200)
  {
    digitalWrite(Led,HIGH);
  }
  else
  {
    digitalWrite(Led,LOW);
  }
  }

Grazie per la disponibilità e l'aiuto!

PS: Mi scuso con il sig. Gugliemo. Ieri non è stata una bella giornata e sono stato molto sgarbato causa problemi personali.. :frowning: :frowning:

LucaAlba98:
Mi scuso con il sig. Gugliemo. Ieri non è stata una bella giornata e sono stato molto sgarbato causa problemi personali.. :frowning: :frowning:

Nessun problema, le "brutte giornate", purtroppo, capitano a tutti ... :frowning:

Riguardo il codice, purtroppo ci devi mettere pesantemente le mani e ... eliminare quelle raffiche di delay() che, ogni volta che chiami la ServoRotation() ... ti BLOCCANO il programma per parecchio tempo tra una chiamata a Distance() ed un altra ...

Per avere un esatto controllo delle temporizzazioni e non avere ritardi, devi NON usare la delay() ed usare la millis() ...
... se non l'hai mai usata/studiata, puoi cominciare a leggere prima QUI, poi QUI ed infine leggi anche QUI e QUI ... vedrai che ti sarà tutto più chiaro.

Guglielmo

La ringrazio molto! oggi mi leggerò bene tutto... comunque lei dice che se sostituisco delay con millis potrò far leggere al sensore la distanza in ogni momento? e quando io invierò una lettera dello switch cosa succederà??
io la lettura della distanza la vorrei in QUALSIASI momento...

In pratica, usando la funzine millis(), che NON è bloccante, sei tu che gestisci i "tempi" in cui avvengono le varie cose ...
... immagina una specie di "scheduler" che schedula, ogni N millesimi di secondo (... anche con vari N relativi a ciascun evento) cosa va fatto.

Ovviamnete all'inizio sembra complesso, ma se ci si prende la mano, il loop() diventa solo un posto dove si controllano le "scadenze temporali" e si richiamano le dovute funzioni.

Guglielmo

Va bene! oggi cercherò di capire bene come funziona e ci lavorerò sopra.. nel caso di dubbi scrivo qui sul forum! Grazie!

Ritorno su questa discussione.. ho inserito la funzione millis nel codice ma ho un grosso problema.. la lettura me la effettua ogni secondo come da me richiesto ma quando invio un comando (tranne l'accensione e lo spegnimento del led) lui non me lo svolge... quale può essere il problema?

Questo il nuovo codice:

#include <NewPing.h>
#include <AFMotor.h>
#include <Servo.h>
#include <SoftwareSerial.h>

#define PingPin A0
NewPing sonar(PingPin,PingPin);
unsigned long previousMillis = 0;
unsigned long interval=1000;
const int speed = 20; //velocità in %
#define RX 15  //A1
#define TX 16 //A2
#define Led 17 //A3 
int data;
int data2;
Servo servo; 
AF_DCMotor Motor_Left_Front(4,MOTOR34_1KHZ);
AF_DCMotor Motor_Right_Front(3,MOTOR34_1KHZ);
AF_DCMotor Motor_Left_Rear(1,MOTOR12_1KHZ);
AF_DCMotor Motor_Right_Rear(2,MOTOR12_1KHZ);
SoftwareSerial btSerial(RX,TX);
void setup() {
  Serial.begin(9600);
  btSerial.begin(9600);
  servo.attach(9);
  servo.write(45);
  pinMode(Led,OUTPUT);
  Motor_Left_Front.setSpeed(255);
  Motor_Right_Front.setSpeed(255);
  Motor_Left_Rear.setSpeed(255);
  Motor_Right_Rear.setSpeed(255);
}

void loop() {
   
    DistanceLoop();
if(btSerial.available())
  {
    data2=btSerial.read();
    Serial.print(data2);
    //data=Serial.read();
    Serial.print(data2, HEX);
    Serial.print(" - ");
    Serial.println((char) data2);
    switch(data2)
     {
      
      case '0'://Reset servo position
      servo.write(45);
      break;
      
      case '1'://Look right
      servo.write(90);
      break;
      
      case '2'://Look left
      servo.write(-90);
      break;

      case '3': //ServoMotor and Distance (HC-SR04)
      ServoRotation();
      break;
      
      case 'O': //Led OFF
      btSerial.print("Led OFF");
      btSerial.print("");
      digitalWrite(Led,LOW);
      break;

      case 'N': //Led ON
      btSerial.print("Led ON");
      btSerial.print("");
      digitalWrite(Led,HIGH);
      break;
      
      case 'F': //Forward
      btSerial.print("FORWARD");
      btSerial.print("");
      Motor_Left_Front.run(FORWARD);
      Motor_Right_Front.run(FORWARD);
      Motor_Left_Rear.run(FORWARD);
      Motor_Right_Rear.run(FORWARD);
      break;

       case 'B': //Backward
       btSerial.print("BACKWARD");
       btSerial.print("");
       Motor_Left_Front.run(BACKWARD);
       Motor_Right_Front.run(BACKWARD);
       Motor_Left_Rear.run(BACKWARD);
       Motor_Right_Rear.run(BACKWARD);
       break;

       case 'S': //Stop
       btSerial.print("STOP");
       btSerial.print("");
       Motor_Left_Front.run(RELEASE);
       Motor_Right_Front.run(RELEASE);
       Motor_Left_Rear.run(RELEASE);
       Motor_Right_Rear.run(RELEASE); 
       break;

       case 'R': //Turn Right 
       btSerial.print("Turn Right");
       btSerial.print("");
       Motor_Left_Front.run(BACKWARD);
       Motor_Right_Front.run(BACKWARD);
       Motor_Left_Rear.run(RELEASE);
       Motor_Right_Rear.run(BACKWARD );
       break;
       
       case 'L': //Turn Left
       btSerial.print("Turn Left");
       btSerial.print("");
       Motor_Left_Front.run(BACKWARD);
       Motor_Right_Front.run(BACKWARD);
       Motor_Left_Rear.run(BACKWARD);
       Motor_Right_Rear.run(RELEASE );
       break;

      }
  }
  }


void ServoRotation()
{
     //senso orario
     servo.write(0);
     delay(300);
     servo.write(45);
     Distance();
     delay(300);
     servo.write(90);
     delay(300);
     //anti-orario
     servo.write(135);
     delay(300);
     servo.write(90);
     delay(300);
     servo.write(45);
     Distance();
     delay(300);
}

void Distance()
{

  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).

  btSerial.print("Distance: ");
  btSerial.print(uS/US_ROUNDTRIP_CM); // convert time into distance
  
  btSerial.println("cm"); 
  btSerial.print("");
  if(uS/US_ROUNDTRIP_CM<10)
  {
       Motor_Left_Front.run(RELEASE);
       Motor_Right_Front.run(RELEASE);
       Motor_Left_Rear.run(RELEASE);
       Motor_Right_Rear.run(RELEASE); 
    }
}

void DistanceLoop()
{
  unsigned long currentMillis=millis();
  if(currentMillis-previousMillis>interval)
  {
    previousMillis=currentMillis;
    Distance();
    }
  }

qui non mi è stata data nessuna risposta però!

@Luca forse non ti è chiara una cosa. Qui NON è un forum di una azienda con personale pagato per rispondere.
Posti la domanda e dopo MENO di 2 ore vuoi risposte!!
Siamo tutti utenti come te, che diamo risposte appena possiamo. Molti lavorano, e visto il periodo, alcuni saranno in ferie.

Certo lo so! Non pretendo una risposta immediata ci mancherebbe! Solo che avevo aperto un'altra discussione per non fare casino con questa ma mi è stata chiusa da Gugliemo perchè era contro il regolamento e mi aveva detto che ci sarebbe stata una risposta qui: ma non la vedo... Comunque aspetto con calma, non ho problemi :slight_smile:

Sig. Gugliemo premetto che ieri ho studiato tutto il materiale da lei gentilmente passato ma oggi sono andato contro questo problema che mi fa dubitare parecchio... sopratutto non capisco perchè non possa andare.. mancanza di corrente forse?

LucaAlba98:
... mi aveva detto che ci sarebbe stata una risposta qui: ma non la vedo ...

Ho scritto :

gpb01:
... ti prego di continuare nel thread che hai già aperto e dove ti sono state già date delle risposte. Grazie.

... nel senso che era un thread già aperto e dove la gente già ti aveva dato delle risposte e quindi ... di continuare nello stesso.

Non ho detto che io ti avevo dato una risposta ... ::slight_smile:

Guglielmo

ah mi scusi ho interpretato malissimo io!
comunque sa darmi qualche info sul problema?? mi ha bloccato tutto il pomeriggio questo pensiero..

qualche buon anima sa aiutarmi?..

Domanda, ma sul monitor seriale, "data2" ti viene stampato sempre correttamemte? Ovvero il carattere arriva e lo vedi giusto?

Guglielmo

P.S.: Per favore, prendi il tuo programma con l'IDE e usa dal menu Tools - > Auto Format, almeno te lo aggiusta che ... attualmente è indentato in modo illegibile ...

allora una cosa che noto subito quando collego il robottino al pc è che il servo che fa girare il sensore hc-sr04 fa dei micromovimenti da me non dati..

ho fatto alcune prove e oggi funziona! Senza cambiare nulla...

infatti con il debug ho questi risultati:

7046 - F
8353 - S
6642 - B
8353 - S
7046 - F
784E - N
794F - O
4931 - 1
4830 - 0
5032 - 2
5032 - 2
4830 - 0
8252 - R
764C - L
764C - L
8353 - S

che sono corretti
l'unica cosa che quando do il comando 1 (ovvero il servo gira a destra per vedere la distanza), la distanza è sempre nulla..
a sinistra e al centro non mi da questi problemi

LucaAlba98:
... l'unica cosa che quando do il comando 1 (ovvero il servo gira a destra per vedere la distanza), la distanza è sempre nulla..
a sinistra e al centro non mi da questi problemi

Riguarda attentamente il codice, magari c'è qualche cosa che ti è sfuggito ... dopo di che inserisci delle Serial.print() dove può essere utile e fatti stampare i valori, così controlli in vari punti di avere ciò che ti aspetti ...

Guglielmo

Il codice è questo (formattato come si deve :wink: ):

#include <NewPing.h>
#include <AFMotor.h>
#include <Servo.h>
#include <SoftwareSerial.h>

#define PingPin A0
NewPing sonar(PingPin, PingPin);
unsigned long previousMillis = 0;
unsigned long interval = 1000;
const int speed = 20; //velocità in %
#define RX 15  //A1
#define TX 16 //A2
#define Led 17 //A3 
int data;
int data2;
Servo servo;
AF_DCMotor Motor_Left_Front(4, MOTOR34_1KHZ);
AF_DCMotor Motor_Right_Front(3, MOTOR34_1KHZ);
AF_DCMotor Motor_Left_Rear(1, MOTOR12_1KHZ);
AF_DCMotor Motor_Right_Rear(2, MOTOR12_1KHZ);
SoftwareSerial btSerial(RX, TX);
void setup() {
  Serial.begin(9600);
  btSerial.begin(9600);
  servo.attach(9);
  servo.write(45);
  pinMode(Led, OUTPUT);
  Motor_Left_Front.setSpeed(255);
  Motor_Right_Front.setSpeed(255);
  Motor_Left_Rear.setSpeed(255);
  Motor_Right_Rear.setSpeed(255);
}

void loop() {

  DistanceLoop();
  if (btSerial.available())
  {
    data2 = btSerial.read();
    Serial.print(data2);
    //data=Serial.read();
    Serial.print(data2, HEX);
    Serial.print(" - ");
    Serial.println((char) data2);
    switch (data2)
    {

      case '0'://Reset servo position
        servo.write(45);
        break;

      case '1'://Look right
        servo.write(90);
        break;

      case '2'://Look left
        servo.write(-90);
        break;

      case '3': //ServoMotor and Distance (HC-SR04)
        ServoRotation();
        break;

      case 'O': //Led OFF
        btSerial.print("Led OFF");
        btSerial.print("");
        digitalWrite(Led, LOW);
        break;

      case 'N': //Led ON
        btSerial.print("Led ON");
        btSerial.print("");
        digitalWrite(Led, HIGH);
        break;

      case 'F': //Forward
        btSerial.print("FORWARD");
        btSerial.print("");
        Motor_Left_Front.run(FORWARD);
        Motor_Right_Front.run(FORWARD);
        Motor_Left_Rear.run(FORWARD);
        Motor_Right_Rear.run(FORWARD);
        break;

      case 'B': //Backward
        btSerial.print("BACKWARD");
        btSerial.print("");
        Motor_Left_Front.run(BACKWARD);
        Motor_Right_Front.run(BACKWARD);
        Motor_Left_Rear.run(BACKWARD);
        Motor_Right_Rear.run(BACKWARD);
        break;

      case 'S': //Stop
        btSerial.print("STOP");
        btSerial.print("");
        Motor_Left_Front.run(RELEASE);
        Motor_Right_Front.run(RELEASE);
        Motor_Left_Rear.run(RELEASE);
        Motor_Right_Rear.run(RELEASE);
        break;

      case 'R': //Turn Right
        btSerial.print("Turn Right");
        btSerial.print("");
        Motor_Left_Front.run(BACKWARD);
        Motor_Right_Front.run(BACKWARD);
        Motor_Left_Rear.run(RELEASE);
        Motor_Right_Rear.run(BACKWARD );
        break;

      case 'L': //Turn Left
        btSerial.print("Turn Left");
        btSerial.print("");
        Motor_Left_Front.run(BACKWARD);
        Motor_Right_Front.run(BACKWARD);
        Motor_Left_Rear.run(BACKWARD);
        Motor_Right_Rear.run(RELEASE );
        break;

    }
  }
}


void ServoRotation()
{
  //senso orario
  servo.write(0);
  delay(300);
  servo.write(45);
  Distance();
  delay(300);
  servo.write(90);
  delay(300);
  //anti-orario
  servo.write(135);
  delay(300);
  servo.write(90);
  delay(300);
  servo.write(45);
  Distance();
  delay(300);
}

void Distance()
{

  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).

  btSerial.print("Distance: ");
  btSerial.print(uS / US_ROUNDTRIP_CM); // convert time into distance

  btSerial.println("cm");
  btSerial.print("");
  if (uS / US_ROUNDTRIP_CM < 10)
  {
    Motor_Left_Front.run(RELEASE);
    Motor_Right_Front.run(RELEASE);
    Motor_Left_Rear.run(RELEASE);
    Motor_Right_Rear.run(RELEASE);
  }
}

void DistanceLoop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval)
  {
    previousMillis = currentMillis;
    Distance();
  }
}

Non penso sia li il problema perchè lo faccio muovere allo stesso modo sia a sinistra che al centro...
La cosa che mi spaventa di più però è il servomotore che sembra che si sforzi a fare movimenti non richiesti quando il robottino viene collegato al pc via usb... o meglio quando gli do alimentazione... ci sono modi per risolverlo??

... mai usato servo, quindi non so dirti, ma ... non vorrei che fosse il posizionamento iniziale quando gli dai corrente ... ::slight_smile:

Guglielmo

intende questa parte di codice nel setup?

servo.write(45);

Uhmm... A cosa serve?