Servomotore + sensore temperatura TMP36

Ciao a tutti,
mi chiamo Marco e questo è il mio primo post su 'Arduino Forum'. Ho comprato da poco il Kit 'Arduino Starter Kit' perchè voglio conoscere meglio il mondo dell'elettronica e della programmazione. Sono arrivato al capitolo cinque del libro in dotazione col Kit. Il capitolo si intitola 'Indicatore d'umore'. Ho costruito e scritto il codice con successo, come spiegato molto bene. Alla fine chiede di provare a far muovere il servomotore con un sensore di temperatura (sensore che ho già visto in uno dei capitolo precedenti).
Ho costruito il circuito come quello proposto nel capitolo cinque sostituendo il potenziometro con il sensore di temperatura TMP36. Per quanto riguarda il codice ho provato a fare un mix tra il capitolo cinque ed il capitolo tre (Amorometro). Purtroppo il servomotore si muove a scatti. Mi sapreste dare dei consigli? Nella modalità 'Serial Monitor', vedo che la temperatura va da i 20.0° ai 30.0° per poi scendere di nuovo vertiginosamente... Incollo il codice:

#include <Servo.h>
Servo myServo;

const int sensorPin = A0;
int sensVal;
float angle;
const float baselineTemp = 20.0;

void setup() {
  myServo.attach(9); 
  Serial.begin(9600);
}

void loop() {
  
  
  // acquisizione valore del sensore di temperatura sul pin A0


  
  sensVal = analogRead(sensorPin);
  Serial.print("Sensor Value: "); 
  Serial.print(sensVal); 


  
  //calcolare la tensione sul piedino
  float voltage = (sensVal/1024.0)* 5.0; 

  Serial.print(", Volts: ");
  Serial.print(voltage);

  Serial.print(", degrees C: ");
  //converto la tensione in temperatura
  float temperature = (voltage - .5) * 100;
  Serial.print(temperature);

  angle = map(temperature, 0, 100, 0, 179);
  Serial.print(", angle: ");
  Serial.println(angle);

  myServo.write(angle);
  delay(15);
  //angle = map(sensVal, 0, 1023, 0, 179);
  //Serial.print(" , angle: ");
  //Serial.println(angle);

  //myServo.write(angle);
  //delay(15);
  
}

Vi ringrazio!

Buonasera e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE (... quello che vedi in blu è un link, fai click su di esso per raggiungere la discussione) spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

1 Like

Grazie gpb01,
ho scritto una breve presentazione di me nella pagina che mi ha consigliato. Chiedo scusa.

Un saluto.

I servomotori economici che sono venduti tipicamente negli starter kit, sono piuttosto imprecisi dal punto di vista meccanico.
Tu poi lo stai comandano ad ogni ciclo di loop() usando un valore che sarà sempre leggermente diverso da quello precedente per la natura stessa del segnale analogico che è affetto da rumore di campionamento (e non solo).

Il risultato è che il tuo servo "vibra" intorno alla posizione teorica che dovrebbe raggiungere.
Prova ad aggiungere un'isteresi al valore letto con analogRead().
Inoltre non ha senso richiamare continuamente l'istruzione servo.write(), ma puoi farlo solo quando il valore di angle è stato effettivamente aggiornato: un classico if(oldAngle != angle) {etc etc} andrà benissimo ad esempio.

Infine, dimenticati dell'esistenza dell'istruzione delay() che purtroppo è stra-abusata negli esempi per principianti. Io la ritengo la fonte della metà dei problemi riscontrati da chi è agli inizi con Arduino.

delay(15) significa che per 15 millisecondi il micro non farà assolutamente nulla; in questo piccolo esempio non è un grande problema, ma quando vorrai iniziare ad eseguire più compiti "contemporaneamente" (ho virgolettato perché non c'è nulla di contemporaneo con un microcontrollore single core), dovrai cercare di evitare il più possibile di implementare algoritmi bloccanti.

La strada maestra nel mondo Arduino (ma non l'unica) è l'uso della funzione millis() su cui troverai tonnellate di documentazione online ed anche qui nel forum.
Lo "schema base" di utilizzo ridotto all'osso è il seguente:

  ...
  // Una variabile dichiarata static mantiene il valore anche se locale
  static unsigned long taskTime;  
  if (millis() - taskTime >= 1000) {
    // Aggiorno taskTime altrimenti l'if sarà sempre vero da qui in poi
    taskTime = millis();

    // Istruzioni che saranno eseguite una volta al secondo
    // come ad esempio un semplice blink di un led
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN);
  }

Ciao cotestatnt,
grazie per la risposta. Provo ad inviarti un video dello schermo eseguendo il codice che ho inoltrato nel primo messaggio per farti vedere che, anche se accosto un dito al sensore, la temperatura non segue un senso logico: dai 17° ai 19° per poi salire a 21° per poi immediatamente scendere.
Video schermo

Stai usando un ADC di soli 10 bit e quindi la precisione è quella che è, però dal video è evidente che hai un'acquisizione del segnale analogico piuttosto rumorosa.
Come hai realizzato il circuito?

Evita le breadboard, salda i cavi ed aggiungi un condensatore elettrolitico da 0.1uF tra il Vccc ed il GND del TMP36.

Sarebbe una buona idea anche usare un partitore di tensione per fare in modo che la tensione di uscita del TMP36 non ecceda il valore di 1.1V
In questo modo puoi impostare la tensione di riferimento interna da 1.1V per l'ADC dell'Arduino e sfruttare al massimo i 10 bit disponibili.

In questo momento infatti stai usando la Vref di default pari a 5V, ma il tuo sensore ha un'uscita massima che arriva a circa 1.6V.

Non solo, i 5V di alimentazione non sono precisi, danno un riferimento grossolano. Somma un'imprecisione di qua e una di là, alla fine l'errore può superare anche il 10%. Servono valori stabili, e una calibrazione usando il voltmetro più preciso a disposizione. Con la calibrazione tutte le tolleranze di resistenze e riferimenti vengono azzerate, e l'errore può scendere allo 0.5%

Naturalmente la calibrazione va fatta con i componenti definitivi già saldati. Cambiando resistenze (anche se hanno lo stesso valore) o Arduino, la calibrazione va rifatta ogni volta.

Vin è la tensione all'ingresso del partitore, misurata con il voltmetro durante la calibrazione. Vmis è la tensione calcolata. ADC è la lettura ottenuta con analogRead.

Grazie ragazzi per le risposte.
Ho provato a disegnare il circuito tramite Tinkercad (link suggerito in un'altra discussione del Forum). Ho spostato la lettura dell'ingresso analogico del sensore (TMP36) sul piedino 'A1'; purtroppo non riuscivo a selezionare il piedino 'A0' sul disegno :sweat_smile: .
ServoMotore + sensore temperatura.pdf (4,4 KB)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.