Conflitto Servo.h con TimerOne.h su Arduino uno

salve.
Ho realizzato un semplice semovente a due ruote con Arduino Uno+motorshield+sonda ultrasuoni montata su un servo.
Il progetto funziona abbastanza bene.

Ho voluto aggiungere due sensori ottici a forcella per controllare gli effettivi giri dei due motori e ho quindi incluso la libreria TimerOne e il relativo codice.

Adesso, sul monitor seriale, leggo i giri delle ruote , ma il servo che permette la rotazione della sonda ultrasuoni, e' immobile. Asteriscando la libreria TimerOne dallo sketch , tutto riprende a funzionare, tranne ovviamente i sensori ottici.

Ho scoperto che la Servo si appoggia su Timer1, quindi immagino che ci sia un conflitto.
Non fornisco altri particolari, perche' stando cosi' le cose, vorrei chiedere solamente se siete a conoscenza di librerie alternative non mutuamente esclusive.

Esiste ,in caso, un workaround?
grazie

Esiste la Servo2 o un un nome del genere, che usa il timer2 invece del timer1

grazie provo a cercarla.

ciao. ho fatto altro prove, ma con esito negativo.
Alla fine ho deciso di fare a meno delle librerie degli interrupt.
Lasciando la Servo, ho scaricato SimpleTimer.

Ho provato il mio sketch base, (gestione motori, servo rotante, sensori ultrasuoni) impostando un timer nel loop principale, che ad ogni secondo stampa un semplice messaggio (tanto per vedere se funzionava tutto assieme).

Visto l'esito positivo, ho collegato il signal del sensore a forcella sul piedino 2 (dichiarato input) e settato l'interrupt 0 per un semplice conteggio in RISING , degli slot della ruota di uno dei motori.
Ad ogni secondo stampo il numero rilevato.

Funziona anche questo, ma stavolta, il solo motore destro non gira piu',(!)
Ho provato a spostare il sensore sul piedino 3 (interrupt 1), ma stesso risultato.

rimosso il codice dell'interrupt, torna tutto in funzione.

Magari non vedo qualcosa di macroscopico. Non capisco perche' funziona solo un motore quando assegno l'interrupt 0 o 1 a qualcosa....

Non dai molte info. A quali pin si collegano i motori ? Quindi ... quale motor shield hai ? (metti pure link a dove hai comprato)

si hai ragione.
utilizzo:

  1. arduino uno

  2. arduino sensor shield v.5.0

  3. motor shield ttps://www.amazon.it/gp/product/B07CHBRF4Z/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1

  4. sensore velocita' https://www.amazon.it/gp/product/B07VSGKQQF/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1

  5. Servo MicroServo TowerPro SG90

  6. Sonda ultrasuoni HC-SR04 4 piedini

questo e' il link del kit, ma considera che la shield motori l'ho riacquistata al link piu' sopra. https://www.amazon.it/gp/product/B074CXBC7H/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1

Collegamenti alla sensor shield:

HC-SR04
GND --> 12G,
ECHO--> 12S
TRIG--> 13S
VCC--> 13V (+5V)

SERVO
GND--->8G
VCC--->8V (+5V)
Signal-->8S

MotorShield
ENA-->6S
IN1-->7S
IN2-->5S
IN3-->4S
IN4--->10S
ENB--->9S
+5V --->10V (+5V) questo e' il piedino che, sulla shield motor, si rende libero, dopo aver rimosso il ponticello fra lui e ENB. Attualmente ignoro perche' debba essere collegato, visto che sensor shield e motor shield, vengono alimentate in parallelo dalle batterie.

Quando ho inserito i sensori a forcella, per fare la prova li ho connessi ai piedini 2 e 3 della sensor shield, dove so che ci sono gli interrupt 0 e 1.

Posta anche il codice con l'interrupt, non mi pare di vedere cose strane nei collegamenti

HEGOM61:
Attualmente ignoro perche' debba essere collegato, visto che sensor shield e motor shield, vengono alimentate in parallelo dalle batterie.

a cosa servono i ponticelli dietro il primo e il quarto pin? a cosa serve il ponticello '5v'?
Risposta:
Un L298 può pilotare 2 motori in DC oppure 1 stepper bipolare. ENA e ENB ENA sono i ponticelli di abilitazione da utilizzare con motori a DC. Non rimuovere i ponticelli nel caso si utilizzi un motore passo-passo. Per pilotare un motore DC servono 3 fili: ENA, IN1 e IN2 (per il secondo motore IN3, IN4 e ENB.
Il ponticello 5V serve, se L298 è alimentato a 12V, ad ottenere sul morsetto 5V l'alimentazione per Arduino (o altra scheda a microC). Se L298 è alimentato a tensioni comprese fra 12V e 24V, scollegare il ponticello e usare il morsetto 5V per prelevare la tensione da Arduino utile per alimentare i circuiti logici di L298[/color]

grazie NID.

se ho capito bene, fino a 12 volts , posso alimentare la motor shield e prelevare 5 volts per arduino al pin VCC. Da 12 in su, tolgo il ponticello dietro ai morsetti dell'alimentazione, e ho 2 circuito separati. uno per i motori che vanno da 12 a 24 V, e l'altro , per la logica, che puo' essere alimentato dai 5 volts di arduino.
Quindi secondo me, il collegamento dal famigerato pin dietro a ENB, e' un refuso del progetto originale, perche' forse l'avevano alimentato con piu' di 12 V, togliendo pero' anche il ponticello dell'alimentazione e separando di fatto i due circuiti. Pero' non mi quadra ancora.....

Ad ogni modo ecco lo sketch (e' un po' lunghetto ma lo devo ottimizzare). Allo stato attuale, non so perche', gira solo il motore di sinistra....

grazie per la pazienza

#include <Servo.h>
#include <SimpleTimer.h>

const int ENA = 6;
const int IN1 = 7;
const int IN2 = 5;
const int IN3 = 4;
const int IN4 = 10;
const int ENB = 9;
const int trigPin = 13;
const int echoPin = 12;
int Tentativi = 0;
int lSPEED = 160;
int rSPEED = 160;
int SensorAngle [7] = {0, 30, 60, 90, 120, 150, 180};
int SensorDistance [7] = {0, 0, 0, 0, 0, 0, 0};
int Angle ;
int Distance = 0;
int OldDistance;
int DistanzaLetta;
int MoveT;
float rotation1;
float rotation2;
boolean MOTOR = true;
boolean MoveHead = true;
// Integers for pulse counters
volatile int counter1 = 0;
volatile int counter2 = 0;
float diskslots = 20;
bool flag = false;
Servo servoHead;
SimpleTimer firstTimer(1000);

void setup() {
 Serial.begin(9600);
 pinMode(ENA, OUTPUT);
 pinMode(IN1, OUTPUT);
 pinMode(IN2, OUTPUT);
 pinMode(IN3, OUTPUT);
 pinMode(IN4, OUTPUT);
 pinMode(ENB, OUTPUT);
 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);
 pinMode(3, INPUT);                // motore sinistro interrupt 0
 servoHead.attach(8);
 Angle = SensorAngle [3];
 ServoScan();
 meanDistance();
 rSPEED = 180;
 lSPEED = 180;
 
 
 attachInterrupt (1, contastep1, RISING);
}

void loop() {

 if (meanDistance() > 30) {
   Serial.println("DISTANZA > 30");
   MoveForward();
   SimpleTimer firstTimer(1000);
   OldDistance = DistanzaLetta;
   Tentativi = 0;
 }
 while (meanDistance() > 30) {
   if (firstTimer.isReady() ) {           
     Serial.print("RUOTA MOTORE 1 ha fatto giri:");
     Serial.println (counter1);  //---------da dividere per 20------------------------------
     counter1 = 0;
     // Do something ...

     // Set the flag so as not to fall into this condition
     flag = true;
     firstTimer.reset();
     SimpleTimer firstTimer(1000);
   }
   Serial.println("WHILE Meandistance>30");
   Serial.println(DistanzaLetta);
   Serial.println(OldDistance);
   if (OldDistance == DistanzaLetta) {
     Tentativi++;
   }
   else {
     Tentativi = 0;
   }
   if (Tentativi >= 3) {
     MoveStop();
     while (meanDistance() > 30 && DistanzaLetta == OldDistance) {
       Serial.println("ASPETTO");
     }
     Tentativi = 0;
   }
   OldDistance = DistanzaLetta;
 }
 ChooseDirection();
}

void ChooseDirection() {
 Serial.println("CHOOSEdirection");
 MoveStop();
 for (Tentativi = 1; Tentativi <= 3; Tentativi++) {
   for (int a = 0; a < 7; a++) {           /* rilevo distanze al momento */
     Angle = SensorAngle [a];
     ServoScan();
     SensorDistance [a] = meanDistance();
   }
   int Dir2Go = 0;                               /* Scelta maggior spazio libero */
   int MaxDistance = SensorDistance[0];
   for ( int a = 0 ; a < 7 ; a++) {
     if (SensorDistance[a] > MaxDistance) {
       Dir2Go = a;
       MaxDistance = SensorDistance [a];
     }
   }
   if (MaxDistance <= 30) {
     MoveT = 500;                 // indietro
     Serial.println("INDIETRO");
     MoveBack();
     MoveT = 600;
     MoveRight();
     MoveStop();
   }
   else {
     if (Dir2Go < 3) {           // sinistra
       Serial.println("SINISTRA");
       MoveT = 500;
       MoveBack();
       MoveT = (200  * (3 - Dir2Go));
       MoveLeft();
       MoveStop();
       break;
     }
     else {                        //destra
       Serial.println("DESTRA");
       MoveT = 500;
       MoveBack();
       MoveT = (200 * (Dir2Go - 3));
       MoveRight();
       MoveStop();
       break;
     }
   }
 }
 Angle = SensorAngle [3];
 ServoScan();
 if (Tentativi >= 3) {
   //  Non si sta muovendo. aspetta di essere rimosso da quella posizione
   while (meanDistance() <= 30) {
     Serial.println("PANICO");
   }
 }
 else {
   Tentativi = 0;
 }
}
// ------------------------------------------------------------------------------------------
void ServoScan()  {
 if (MoveHead == true) {
   //Serial.println ("SERVOSCAN");
   servoHead.write(Angle);
   delay(15);
   //delay(1000);
 }
}
//-------------------------------------------------------------------------------------------
float pingSensor() // returns the distance (cm)
{
 long duration;
 float distance;
 digitalWrite(trigPin, HIGH); // We send a 10us pulse
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH, 20000); // We wait for the echo to come back, with a
 // timeout of 20ms, which corresponds
 // approximately to 3m
 // pulseIn will only return 0 if it timed out.
 // (or if echoPin was already to 1, but it should not happen)
 if (duration == 0) // if we timed out
 {
   pinMode(echoPin, OUTPUT); // Then we set echo pin to output mode
   digitalWrite(echoPin, LOW); // We send a LOW pulse to the echo pin
   delayMicroseconds(200);
   pinMode(echoPin, INPUT); // And finaly we come back to input mode
 }
 distance = (duration / 2.0) / 29.1;
 return distance; //We return the result. Here you can find a 0 if we timed out
}

//-------------------------------------------------------------------------
float meanDistance() {
 float mD = 0;                 // conterranno la media delle letture, e le letture stesse
 float DX [15];
 for (int a = 0; a < 15; a++) {
   DX[a] = pingSensor();
   delay(20);   // NON TOCCARE!!!!!!!!!!!!!!!!!!!!!
 }
 for (int a = 0; a < 15; a++) {
   mD = mD + DX [a];
 }
 mD = mD / 15;
 DistanzaLetta = mD;
 return mD;
}



void MoveBack() {
 if (MOTOR) {
   Serial.println("INDIETRO");
   analogWrite(ENA, lSPEED);
   digitalWrite(IN1, HIGH );
   digitalWrite(IN2, LOW);
   analogWrite(ENB, rSPEED);
   digitalWrite(IN3, HIGH);
   digitalWrite(IN4, LOW);
   delay (MoveT);
   MoveStop();

 }
}

void MoveStop() {
 Serial.println("STOP");
 analogWrite(ENA, 0);
 digitalWrite(IN1, LOW );
 digitalWrite(IN2, LOW);
 analogWrite(ENB, 0);
 digitalWrite(IN3, LOW);
 digitalWrite(IN4, LOW);

}

void MoveForward() {
 Serial.println("FORWARD");
 if (MOTOR) {
   analogWrite(ENA, lSPEED);
   digitalWrite(IN1, LOW );
   digitalWrite(IN2, HIGH);
   analogWrite(ENB, rSPEED);
   digitalWrite(IN3, LOW);
   digitalWrite(IN4, HIGH);

 }
}

void MoveLeft() {
 if (MOTOR) {
   analogWrite(ENA, lSPEED);
   digitalWrite(IN1, HIGH );
   digitalWrite(IN2, LOW);
   analogWrite(ENB, rSPEED);
   digitalWrite(IN3, LOW);
   digitalWrite(IN4, HIGH);
   delay (MoveT);
   MoveStop();

 }
}

void MoveRight() {
 if (MOTOR) {
   analogWrite(ENA, lSPEED);
   digitalWrite(IN1, LOW );
   digitalWrite(IN2, HIGH);
   analogWrite(ENB, rSPEED);
   digitalWrite(IN3, HIGH);
   digitalWrite(IN4, LOW);
   delay (MoveT);
   MoveStop();

 }
}

void contastep1() {
 counter1++;
}

>HEGOM61: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non avrai sistemato il codice come richiesto, nessuno ti potrà rispondere, quindi ti consiglio di farlo al più presto. :wink:

ok fatto, grazie

ma sono visibile adesso dopo le modifiche?

Certo, lo sei SEMPRE stato ! :slight_smile:

Guglielmo