Progettino con sensore ultrasonico

ciao a tutti e buon 2026 :wink:

Per Natale ho acquistato un kit con 35 modulini sensori per mio figlio ed adesso li stiamo testando. Abbiamo testato il sensore ultrasonico con il programma suggerito per misurare le distanze e il tutto funziona perfettamente.

Prendendo spunto da quel programma, volevamo creare un progettino che in base alla distanza (max 3m) scrivesse su un display numerico led i numeri 1, 2 e 3 e sotto il metro di distanza attivasse il servo per sparare con un cannoncino lego :grinning_face_with_smiling_eyes:

Leggendo la lettura della distanza sul il monitor seriale, noto che il sensore rileva tutto perfettamente sopra ai 3m, mentre quando attiva una delle routine al di sotto dei 3m pare smetta di rilevare ed entri in loop (sul monitor leggo sempre 0 cm ed anche la frequenza rallenta) :thinking:

Non riesco a capire dove stia l’errore nel codice, potete darmi una mano? Grazie in anticipo!


#include <Servo.h>
Servo myServo;

unsigned long prevMillis = 0;
unsigned long currMillis = 0;
const long segLed = 550; // durata di 0,55 sec del segmento led acceso
int angolo = 0; // variabile per impostare l'angolo di rotazione del servo
int ledPin = 0; // variabile per i pin del display

const int TRIG_PIN1 = 12; // trigger pin sensore ultrasonico 
const int ECHO_PIN1 = 3; // echo pin sensore ultrasonico
long duration1 = 0;
int cm = 0;


void setup() {
  for (int ledPin = 3; ledPin <= 10; ledPin++) { // i led del display numerico vanno dal pin 3 al 10
    pinMode(ledPin, OUTPUT); // pin dei led in output
    digitalWrite(ledPin, LOW);// tutti led spenti
  }
  ledPin = 4; // imposto il primo segmento del display da accendersi (segmento C)
  pinMode(2, OUTPUT);
  pinMode(TRIG_PIN1, OUTPUT);
  pinMode(ECHO_PIN1, INPUT);
  Serial.begin(9600);

  delay(1000);
}

void loop() {
  pinMode(2, OUTPUT);
  digitalWrite(2, LOW); // comando del servo a zero
  currMillis = millis();

  digitalWrite(TRIG_PIN1, LOW);
  delayMicroseconds(5);
  digitalWrite(TRIG_PIN1, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN1, LOW);
  duration1 = pulseIn(ECHO_PIN1, HIGH);
  cm = (duration1 / 2) / 29.1; // Divide by 29.1 or multiply by 0.0343

  Serial.print(cm);
  Serial.println(" cm distanza sensore");

  if (cm > 301) { // se sono distante dal sensore piu“ di 3 metri
  sopra3m();
  } else if (cm > 200  && cm <= 300){ // se sono distante dal sensore tra i 2 ed 3 metri
  tra2e3();
  } else if (cm > 100  && cm <= 200){ // se sono distante dal sensore tra i 1 ed 2 metri
  tra1e2();
  } else if (cm > 10  && cm <= 100){ // se sono distante dal sensore tra i 10 cm ed 1 metro
  sotto1();
  }

  delay(300); // ritardo per evitare doppie letture
}

void sopra3m() { // se sono distante piu“ di 3 metri dal sensore, il display led fa girare un segmento in senso orario
    if (currMillis - prevMillis >= segLed) { // controllo se son passati gli 0,55 sec dall'accensione del segmento led di prima
    if (ledPin >= 10){
      for (int ledPin = 3; ledPin <= 10; ledPin++) {
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
  }
  ledPin = 4;
  digitalWrite(ledPin, HIGH);
  }
  if (ledPin >= 4 && ledPin <= 8) { // se non ho ancora acceso l'ultimo segmento del display
    digitalWrite(ledPin, LOW); // spengo il segmento acceso in precedenza
    ledPin++; // incremento la variabile dei pin del display per accendere il segmento successivo
    digitalWrite(ledPin, HIGH); // accendo il segmento
  } else if (ledPin == 9){ // quando ho acceso l'ultimo segmento collegato al pin Arduino 9
    digitalWrite(ledPin, LOW);
    ledPin = 4; // re-imposto la variabile dei led a 4, pin di Arduino collegato al primo segmento, e inizio nuovamente la sequenza
    digitalWrite(ledPin, HIGH);
    }
  prevMillis = currMillis;
  } 
}

void tra2e3() { // se sono distante tra 2 e 3 metri, scrivo il numero 3 sul display
  for (int ledPin = 3; ledPin <= 10; ledPin++) {
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
  }
  digitalWrite(8, HIGH); // scrivo il numero 3
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
}

void tra1e2(){ // se sono distante tra 1 e 2 metri, scrivo il numero 2 sul display
  for (int ledPin = 3; ledPin <= 10; ledPin++) {
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
  }
  digitalWrite(8, HIGH); // scrivo il numero 2
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
}

void sotto1(){ // se sono piu“ vicino di 1 metro, scrivo il numero 1 sul display ed attivo il servo per sparare il lego
  for (int ledPin = 3; ledPin <= 10; ledPin++) { 
    pinMode(ledPin, OUTPUT); 
    digitalWrite(ledPin, LOW); 
  }
  digitalWrite(9, HIGH); // scrivo il numero 1
  digitalWrite(4, HIGH);

  myServo.attach(2); // imposto il pin di comando del servo sul 2
  angolo = 90; // imposto l'angolo di 90 gradi per il servo
  myServo.write(angolo); // muovo il servo
  delay (1000); // attendo 1 secondo
  angolo = 0; // imposto l'angolo a 0 per il servo
  myServo.write(angolo); // riposiziono il servo
  delay(3000); // attendo 3 secondi
}

Ma sei sicuro?
In tutti i tuoi casi pin 3 (echo) viene impostato come output >> LOW. Perche' ?
PinMode non deve essere chiamato in continuazione in loop (nemmeno servo.attach) ma solo una volta in setup.

sul fatto che sopra i 3 metri misuri sempre son sicuro (difatti nel monitor seriale vedo la distanza che cambia se muovo il sensore su diversi ostacoli, ed il display numerico fa il ciclo con il segmento che ruota).

my.servo() hai ragione, errore da principiante :wink: ed i pinMode li richiamo per azzerare il display ogni volta che devo scrivere un altro numero. Sicuramente ci saraĀ“ un modo migliore, ma pensi che richiamarli piuĀ“ volte crei problemi all’esecuzione del programma?

Non dovrebbe influire con le misurazioni dei sensori :thinking:

Non fa nessun senso per me..
Ma inizi da pin3, echo pin. Perche' lo metti output>>LOW??

cavoli hai trovato l’errore! Non devo iniziare infatti da pin3, ma dal 4!

errore percheĀ“ ho copiato un precedente programma dove avevo il display collegato al 3…non so se questa correzione risolva il programma, proveroĀ“ piuĀ“ tardi, ma grazie per il debug :upside_down_face: ieri sera ho controllato il codice diverse volte e non l’avevo visto, avere due occhi esterni (ed esperti) aiuta!

problema risolto e codice semplificato, ora funziona!

Grazie kmin :wink:

#include <Servo.h>
Servo myServo;

unsigned long prevMillis = 0; // variabile per il conteggio del tempo precedente
unsigned long currMillis = 0; // variabile per il conteggio del tempo attuale
const long segLed = 550; // durata di 0,55 sec del segmento led acceso
int angolo = 0; // variabile per impostare l'angolo di rotazione del servo
int ledPin = 0; // variabile per i pin del display

const int TRIG_PIN1 = 12; // trigger pin sensore ultrasonico
const int ECHO_PIN1 = 3; // echo pin sensore ultrasonico
long duration1 = 0;
int cm = 0;

void setup() {
  for (int ledPin = 4; ledPin <= 10; ledPin++) { // i led del display numerico vanno dal pin 4 al 10
    pinMode(ledPin, OUTPUT); // pin dei led in output
    digitalWrite(ledPin, LOW);// tutti led spenti
  }
  ledPin = 4; // imposto il primo segmento del display da accendersi (segmento C)
  
  myServo.attach(2); // imposto il pin di comando del servo sul 2
  angolo = 0; // imposto l'angolo a 0 per il servo
  myServo.write(angolo); // riposiziono il servo

  pinMode(2, OUTPUT);
  pinMode(TRIG_PIN1, OUTPUT);
  pinMode(ECHO_PIN1, INPUT);
  Serial.begin(9600);

  delay(1000);
}

void loop() {
  digitalWrite(2, LOW); // comando del servo a zero
  currMillis = millis();

  digitalWrite(TRIG_PIN1, LOW);
  delayMicroseconds(5);
  digitalWrite(TRIG_PIN1, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN1, LOW);
  duration1 = pulseIn(ECHO_PIN1, HIGH);
  cm = (duration1 / 2) / 29.1; // Divide by 29.1 or multiply by 0.0343

  Serial.print(cm);
  Serial.println(" cm distanza sensore");

  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  digitalWrite(10, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);

  if (cm > 301) { // se sono distante dal sensore piu“ di 3 metri
    if (currMillis - prevMillis >= segLed) { // controllo se son passati gli 0,55 sec dall'accensione del segmento led di prima
      if (ledPin >= 10){
        digitalWrite(8, LOW);
        digitalWrite(9, LOW);
        digitalWrite(10, LOW);
        digitalWrite(4, LOW);
        digitalWrite(5, LOW);
        digitalWrite(6, LOW);
        digitalWrite(7, LOW);
      }
    ledPin = 4;
    digitalWrite(ledPin, HIGH);
    }
    if (ledPin >= 4 && ledPin <= 8) { // se non ho ancora acceso l'ultimo segmento del display
      digitalWrite(ledPin, LOW); // spengo il segmento acceso in precedenza
      ledPin++; // incremento la variabile dei pin del display per accendere il segmento successivo
      digitalWrite(ledPin, HIGH); // accendo il segmento
    } else if (ledPin == 9){ // quando ho acceso l'ultimo segmento collegato al pin Arduino 9
      digitalWrite(ledPin, LOW);
      ledPin = 4; // re-imposto la variabile dei led a 4, pin di Arduino collegato al primo segmento, e inizio nuovamente la sequenza
      digitalWrite(ledPin, HIGH);
      }
    prevMillis = currMillis;

  } else if (cm > 200  && cm <= 300){ // se sono distante dal sensore tra i 2 ed 3 metri, scrive 3
      digitalWrite(8, HIGH); // scrivo il numero 3
      digitalWrite(9, HIGH);
      digitalWrite(10, HIGH);
      digitalWrite(4, HIGH);
      digitalWrite(5, HIGH);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);

  } else if (cm > 100  && cm <= 200){ // se sono distante dal sensore tra i 1 ed 2 metri, scrive 2
      digitalWrite(8, HIGH); // scrivo il numero 2
      digitalWrite(9, HIGH);
      digitalWrite(10, HIGH);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, LOW);
      digitalWrite(4, LOW);

  } else if (cm > 10  && cm <= 100){ // se sono distante dal sensore tra i 10 cm ed 1 metr0, scrive 1 e spara
      digitalWrite(9, HIGH); // scrivo il numero 1
      digitalWrite(4, HIGH);
      digitalWrite(10, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);

      angolo = 90; // imposto l'angolo di 90 gradi per il servo
      myServo.write(angolo); // muovo il servo
      delay (1000); // attendo 1 secondo
      angolo = 0; // imposto l'angolo a 0 per il servo
      myServo.write(angolo); // riposiziono il servo
      delay(3000); // attendo 3 secondi
    }
  delay(300);
}

Bene!