Per il conseguimento del diploma di maturità ho dovuto produrre un elaborato sulla creazione di un pappagallo giocattolo con delle funzionalità interattive.
- Rilevanza movimenti
- Ricerca e percezione della distanza
- Riprodurre versi e il battito di ali
- Ascoltare, registrare
- Riprodurre delle registrazioni
Tramite il microcontrollore ESP32 programmato in C++ ho gestito le varie operazioni, tra le quali mi sono occupato personalmente del campionamento e del salvataggio delle registrazioni in un formato audio raw. Il codice si trova sul mio
github assieme alla documentazione, l'implementazione è pulita e semplice grazie al paradigma OOP.
Per motivi sconosciuti il recording presenta un'amplificazione audio strana, ho concretamente prodotto la circuiteria ad eccezione dell'implementazione dei motori per il battito delle ali. Le componenti usate sono
- Esp 32
- Sensore PIR e sensore ultrasuoni: HC-SR04P
- MAX9841 microfono, con lm2937 per ripulire i possibili disturbi di linea
- MAX98357A modulo amplificatore
- Servomotori per modificare la direzione del sensore ultrasuoni
- Motorini per il battito ali
/* LOOP CODE */
void loop() {
unsigned long timer_normalize= millis();
int secondi= (int)millis()/1000;
int human_distance; //Distanza pappagallo - uomo
if (motion) { //Controllo se ci sono stati movimenti
human_distance= poldo.check_humans_near(); //Mi cerco intorno umani vicino a me
if (human_distance==0){ //Se non ho trovato nessuno mi disattivo
poldo.Dormi();
if (secondi-timer>=10){
timer= secondi;
poldo.Batti_ali();
poldo.Reproduce("Verso.wav");
//poldo.Batti_ali(); with DC motor uncomment
motion-= 2; //Diminuisco attività nella stanza
}
} else { //Altrimenti controllo a che distanza sta l'umano
motion= 10;
timer_normalize= millis();
poldo.Sveglio();
if (human_distance<70){ //Se è vicino almeno 70cm gli chiedo di parlarmi e io ascolto
poldo.Batti_ali();
poldo.Reproduce("Talk_me.wav");//Parlami che ripeto audio
//poldo.Batti_ali(); with DC motor uncomment
detachInterrupt(digitalPinToInterrupt(PIR));
//disabilito interrupt per evitare conflitti nella funzione record
poldo.wait_noise(9, 3); //Aspetto che qualcuno mi parli, impostando un timeout
//La variabile anyone_talk restituisce true se wait noise ha sentito qualcosa nel campionamento
if (poldo.anyone_talk()){
poldo.Record(5);
//Ascolto per 5 secondi chi mi sta parlando, con campione precedente
for (int i= 0; i<3; i++){
poldo.Batti_ali();
poldo.Ripeti();//Ripeto ciò che mi è stato detto
//poldo.Batti_ali(); with DC motor uncomment
}
}
attachInterrupt(digitalPinToInterrupt(PIR), getMotion, RISING);
} else {
if (secondi-timer_vieni>5){
poldo.Batti_ali();
poldo.Reproduce("Come_here.wav");
timer_vieni= secondi;
}
}
timer= secondi;
}
}
int delta= 1000-((millis()-timer_normalize)%1000);//milliseconds to normalize time
delay(delta);//Normalize time, loop recycle every second
}
Allora nell'implementazione hardware-software basti definire il ruolo di ogni pin e l'oggetto Pappagallo Poldo la cui applicazione logica è presentata nel precedente codice.
-
Impostiamo una nozione di presenza che sveglia il pappagallo per 10 motion,
-
Impostare il sensore ultrasuoni: TRIG, ECHO e il sensore di movimento PIR. Tutto ciò si collega a Poldo.
-
Si istruisce il microfono del pappagallo e l'altoparlante:
poldo.setReproducer(I2S_BCLK, I2S_LRC, I2S_DOUT, 2);
poldo.setMic(ADC1_CHANNEL_5);
-
Si mette a dormire Poldo attivando un sistema di sveglia tramite un interrupt fisico.
Da notare la necessità di essere volatile la variabile motion.
-
#include<ESP32_Servo.h>
#include"Pappagallo.h"
#define FILESYSTEM SPIFFS
#define ALI 4
#define HEAD 2
#define LED 15
#define TRIG 5
#define PIR 14
#define ECHO 13
#define I2S_DOUT 25
#define I2S_BCLK 27 // I2S
#define I2S_LRC 26
Pappagallo poldo(HEAD, ALI, "Poldo");
volatile int motion= 10;
int timer, timer_vieni;
void getMotion(){
motion= 10;
}
/* SETUP CODE */
void setup() {
FILESYSTEM.begin(true);
Serial.begin(115200);
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(PIR, INPUT);
pinMode(RESET, INPUT);
poldo.setDistanceSensor(TRIG, ECHO);
poldo.setReproducer(I2S_BCLK, I2S_LRC, I2S_DOUT, 2);
poldo.setMic(ADC1_CHANNEL_5);
poldo.setLight(2);
poldo.Dormi();
attachInterrupt(digitalPinToInterrupt(PIR), getMotion, RISING);
timer_vieni= -5;
}