- Modificato
Introduzione:
In questa guida vedremo come creare un circuito Arduino che tramite dei fotoresistori e servomotori (di posizione) ci permette di mantenere sempre perpendicolare il pannello solare rispetto alla fonte di luce.
Il primo servomotore si occupa dei movimenti verticali, UpDown
regola l'angolo del servo1 in base ai valori dei fotoresistori della parte superiore sensorTop
e inferiore sensorBottom
del pannello. Se il valore del fotoresistore superiore sensorTop
è più basso di quello inferiore sensorBottom
, il servomotore servo1 incrementa la sua posizione per spostare il pannello solare verso l'alto, se sensorTop
è maggiore di sensorBottom
, servo1 torna indietro per spostare il pannello solare verso il basso.
Il secondo servomotore invece controlla i movimenti orizzontali del pannello, il comportamento è simile al primo, si inverte solo l'asse.
Materiali:
- Arduino UNO
- 4 Fotoresistori (LDR - Light Dependent Resistors)
- 2 Servomotori
- Display (LCD)
- Svariati cavi e Breadboard
- 4 Resistenze da 10 kΩ
- 2 Resistenze da 1 kΩ
- Vari supporti per il pannello solare
- Pannello solare (su Tinkercad da 5 V, 100 mA)
Collegamento:
Illustrato il funzionamento generale del circuito vediamo subito i collegamenti:
Inizialmente colleghiamo l'alimentazione ad una fila positiva della breadboard (idem per la negativa) e successivamente con dei cavi la disponiamo anche per le 2 file rimanenti.
I servomotori sono composti da 3 uscite, rispettivamente: segnale, alimentazione e terra.
Per il primo servo si collega il segnale al pin 9 di Arduino mentre per il secondo servo al pin 10, se avete dei cavi troppo piccoli per comodità potete fare da ponte con la breadboard. Per tutti e due i motori collegate alimentazione e terra alla fila + e - della breadboard.
Per collegare il Display LCD: pin RS al pin 12, pin E al pin 11, pin D4, D5, D6 e D7 ai pin 5, 4, 3, e 2 rispettivamente, pin RW a terra e i pin di alimentazione (VCC e GND) alle rispettive file della breadboard (Vedi l'immagine per le eventuali resistenze da 1 kΩ).
I fotoresistori vanno collegati alle porte analogiche di Arduino (A0, A1, A3, A4), l'estremità superiore dei fotoresistori va collegata al + (5V) mentre l'estremità inferiore a GND, qui sono molto importanti le resistenze da 10 kΩ (vedi l'immagine).
Codice:
Inserimento librerie:
#include <LiquidCrystal.h>
#include <Servo.h>
LiquidCrystal e Servo necessarie per gestire un display LCD e un motore servo in ambiente Arduino (su Tinkercad sono disponibili automaticamente).
Dichiarazione funzioni:
void moveUpDown(int sensorTop, int sensorBottom, Servo& servoUpDown);
void moveLeftRight(int sensorLeft, int sensorRight, Servo& servoLeftRight);
moveUpDown
e moveLeftRight
ricevono come parametri i valori letti dai fotosensori e i servo corrispondenti.
Dichiarazione dei servomotori e del display LCD:
Servo servoUpDown;
Servo servoLeftRight;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Qui vengono dichiarati il servo per controllare i due servomotori (servoUpDown
e servoLeftRight
) e LiquidCrystal
per gestire il display LCD.
setup():
void setup() {
lcd.begin(16, 2);
lcd.print("Servo UD");
lcd.setCursor(0, 1);
lcd.print("Servo LR");
servoUpDown.attach(9);
servoLeftRight.attach(10);
servoUpDown.write(90);
servoLeftRight.write(90);
}
Il setup
viene eseguito una sola volta all'inizio: inizializza il display LCD, visualizza i dati iniziali, collega i pin dei servomotori e posiziona i servomotori a 90 gradi.
loop():
void loop() {
int sensorTop = analogRead(A0);
int sensorBottom = analogRead(A1);
int sensorLeft = analogRead(A3);
int sensorRight = analogRead(A4);
int avgUpDown = (sensorTop + sensorBottom) / 2;
int avgLeftRight = (sensorLeft + sensorRight) / 2;
if (avgUpDown > avgLeftRight) {
moveUpDown(sensorTop, sensorBottom, servoUpDown);
} else if (avgUpDown < avgLeftRight) {
moveLeftRight(sensorLeft, sensorRight, servoLeftRight);
}
delay(10);
}
Il loop
invece viene eseguito ininterrottamente: legge i valori dai sensori e calcola le medie avgUpDown
e avgLeftRight
. In base al confronto tra queste medie chiama la funzione appropriata (moveUpDown
o moveLeftRight
). delay(10)
per evitare un loop troppo veloce.
moveUpDown
void moveUpDown(int sensorTop, int sensorBottom, Servo& servoUpDown) {
int posUpDown = servoUpDown.read();
if (sensorTop < sensorBottom) {
posUpDown--;
} else {
posUpDown++;
}
servoUpDown.write(posUpDown);
lcd.setCursor(12, 0);
lcd.print(posUpDown);
}
In questo caso si controlla il servo per il movimento su e giù in base ai valori dei sensori in particolare legge la posizione del servo, la aggiorna in base alla differenza tra i sensori superiori e inferiori e di conseguenza scrive la nuova posizione sul servo e sul display LCD.
moveLeftRight
void moveLeftRight(int sensorLeft, int sensorRight, Servo& servoLeftRight) {
int posLeftRight = servoLeftRight.read();
if (sensorLeft < sensorRight) {
posLeftRight--;
} else {
posLeftRight++;
}
servoLeftRight.write(posLeftRight);
lcd.setCursor(12, 1);
lcd.print(posLeftRight);
}
Simile a moveUpDown
ma si cambia asse.
Codice completo:
#include <LiquidCrystal.h>
#include <Servo.h>
void moveUpDown(int sensorTop, int sensorBottom, Servo& servoUpDown);
void moveLeftRight(int sensorLeft, int sensorRight, Servo& servoLeftRight);
Servo servoUpDown;
Servo servoLeftRight;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
lcd.begin(16, 2);
lcd.print("Servo UD");
lcd.setCursor(0, 1);
lcd.print("Servo LR");
servoUpDown.attach(9);
servoLeftRight.attach(10);
servoUpDown.write(90);
servoLeftRight.write(90);
}
void loop() {
int sensorTop = analogRead(A0);
int sensorBottom = analogRead(A1);
int sensorLeft = analogRead(A3);
int sensorRight = analogRead(A4);
int avgUpDown = (sensorTop + sensorBottom) / 2;
int avgLeftRight = (sensorLeft + sensorRight) / 2;
if (avgUpDown > avgLeftRight) {
moveUpDown(sensorTop, sensorBottom, servoUpDown);
} else if (avgUpDown < avgLeftRight) {
moveLeftRight(sensorLeft, sensorRight, servoLeftRight);
}
delay(10);
}
void moveUpDown(int sensorTop, int sensorBottom, Servo& servoUpDown) {
int posUpDown = servoUpDown.read();
if (sensorTop < sensorBottom) {
posUpDown--;
} else {
posUpDown++;
}
servoUpDown.write(posUpDown);
lcd.setCursor(12, 0);
lcd.print(posUpDown);
}
void moveLeftRight(int sensorLeft, int sensorRight, Servo& servoLeftRight) {
int posLeftRight = servoLeftRight.read();
if (sensorLeft < sensorRight) {
posLeftRight--;
} else {
posLeftRight++;
}
servoLeftRight.write(posLeftRight);
lcd.setCursor(12, 1);
lcd.print(posLeftRight);
}