#include <Wire.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Ultrasonic.h>
#include <LIDARLite_v3HP.h>
#include <Kalman.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <TensorFlowLite.h>
#include <FastLED.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <Servo.h>
// Definizioni dei pin
namespace Pin {
constexpr uint8_t MOTOR_LEFT_FORWARD = 9;
constexpr uint8_t MOTOR_LEFT_BACKWARD = 8;
constexpr uint8_t MOTOR_RIGHT_FORWARD = 7;
constexpr uint8_t MOTOR_RIGHT_BACKWARD = 6;
constexpr uint8_t TRIGGER = 12;
constexpr uint8_t ECHO = 11;
constexpr uint8_t CAMERA = 10;
constexpr uint8_t ARM_LEFT = 4;
constexpr uint8_t ARM_RIGHT = 5;
constexpr uint8_t LED = 2;
constexpr uint8_t BUZZER = 3;
}
// Configurazione della rete
namespace Network {
const char* const WIFI_SSID = "YOUR_SSID";
const char* const WIFI_PASSWORD = "YOUR_PASSWORD";
const char* const MQTT_SERVER = "YOUR_MQTT_SERVER";
const char* const NTP_SERVER = "pool.ntp.org";
}
// Sensori e librerie
Ultrasonic ultrasonic(Pin::TRIGGER, Pin::ECHO);
Adafruit_MPU6050 mpu;
LIDARLite_v3HP lidar;
Kalman kalmanX, kalmanY, kalmanZ;
FastLED leds(1, Pin::LED, WS2812);
// PID e controllo
constexpr double KP = 2.0;
constexpr double KI = 5.0;
constexpr double KD = 1.0;
double input, output, setpoint;
PID pidController(&input, &output, &setpoint, KP, KI, KD, DIRECT);
// Configurazione di rete e MQTT
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
WiFiUDP udpClient;
NTPClient ntpClient(udpClient, Network::NTP_SERVER, 3600); // UTC +1 ora
// TensorFlow Lite
namespace TensorFlowLite {
tflite::MicroInterpreter* interpreter = nullptr;
tflite::MicroErrorReporter errorReporter;
tflite::Model* model = nullptr;
tflite::MicroOpResolver<10> opResolver;
tflite::DynamicBuffer tensorArena;
constexpr int TENSOR_ARENA_SIZE = 1024 * 10;
}
// Stati emotivi
enum class Emotion { HAPPY, SAD, CURIOUS, ANGRY };
Emotion currentEmotion = Emotion::HAPPY;
// Servomotori per braccia e gambe
Servo armLeft;
Servo armRight;
Servo legLeft;
Servo legRight;
// Struttura per la gestione dei motori e delle braccia
class ActuatorController {
public:
static void initialize() {
armLeft.attach(Pin::ARM_LEFT);
armRight.attach(Pin::ARM_RIGHT);
legLeft.attach(Pin::ARM_LEFT); // Usa pin separati se disponibili
legRight.attach(Pin::ARM_RIGHT); // Usa pin separati se disponibili
}
static void setMotorSpeeds(int leftMotorSpeed, int rightMotorSpeed) {
analogWrite(Pin::MOTOR_LEFT_FORWARD, constrain(leftMotorSpeed, 0, 255));
analogWrite(Pin::MOTOR_RIGHT_FORWARD, constrain(rightMotorSpeed, 0, 255));
analogWrite(Pin::MOTOR_LEFT_BACKWARD, constrain(-leftMotorSpeed, 0, 255));
analogWrite(Pin::MOTOR_RIGHT_BACKWARD, constrain(-rightMotorSpeed, 0, 255));
}
static void setArmSpeeds(int leftArmSpeed, int rightArmSpeed) {
armLeft.write(constrain(leftArmSpeed, 0, 180));
armRight.write(constrain(rightArmSpeed, 0, 180));
}
static void setLegSpeeds(int leftLegSpeed, int rightLegSpeed) {
legLeft.write(constrain(leftLegSpeed, 0, 180));
legRight.write(constrain(rightLegSpeed, 0, 180));
}
};
// Funzioni di lettura dei sensori
float getUltrasonicDistance() {
return ultrasonic.read();
}
float getLidarDistance() {
return lidar.distance();
}
void updateIMU() {
sensors_event_t accelerometerEvent, gyroEvent, tempEvent;
mpu.getEvent(&accelerometerEvent, &gyroEvent, &tempEvent);
kalmanX.update(accelerometerEvent.acceleration.x, gyroEvent.gyro.x);
kalmanY.update(accelerometerEvent.acceleration.y, gyroEvent.gyro.y);
kalmanZ.update(accelerometerEvent.acceleration.z, gyroEvent.gyro.z);
}
void takePicture() {
Serial.println("Taking picture...");
// Implementazione del controllo della camera
}
void recordVideo() {
Serial.println("Recording video...");
// Implementazione del controllo della camera
}
// Funzione di controllo avanzato con PID
void advancedControl() {
updateIMU();
input = kalmanX.getAngle();
pidController.Compute();
ActuatorController::setMotorSpeeds(static_cast<int>(output), static_cast<int>(output));
}
// Funzione di inferenza avanzata con TensorFlow Lite
void inferTensorFlowLite() {
interpreter->Invoke();
// Elaborazione dei risultati di inferenza
}
// Comportamento di evitamento ostacoli avanzato
void avoidObstacles() {
currentEmotion = Emotion::ANGRY;
updateEmotion();
delay(100);
ActuatorController::setMotorSpeeds(0, 255); // Gira a destra
delay(300);
ActuatorController::setMotorSpeeds(0, 0); // Ferma il robot
currentEmotion = Emotion::HAPPY;
updateEmotion();
}
// Gestione della rete e MQTT
void reconnectToMQTT() {
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqttClient.connect("ArduinoClient")) {
Serial.println("Connected");
mqttClient.subscribe("robot/commands");
} else {
Serial.print("Failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void handleMQTTMessage(char* topic, byte* payload, unsigned int length) {
DynamicJsonDocument jsonDoc(1024);
DeserializationError error = deserializeJson(jsonDoc, payload, length);
if (error) {
Serial.print("JSON deserialization error: ");
Serial.println(error.c_str());
return;
}
if (strcmp(topic, "robot/commands") == 0) {
String command = jsonDoc["command"];
if (command == "forward") {
ActuatorController::setMotorSpeeds(255, 255);
} else if (command == "backward") {
ActuatorController::setMotorSpeeds(-255, -255);
} else if (command == "stop") {
ActuatorController::setMotorSpeeds(0, 0);
} else if (command == "picture") {
takePicture();
} else if (command == "video") {
recordVideo();
}
}
}
void updateEmotion() {
switch (currentEmotion) {
case Emotion::HAPPY:
ActuatorController::setMotorSpeeds(255, 255);
ActuatorController::setArmSpeeds(180, 180); // Braccia completamente estese
ActuatorController::setLegSpeeds(180, 180); // Gambe completamente estese
leds.setBrightness(255);
leds.show();
break;
case Emotion::SAD:
ActuatorController::setMotorSpeeds(0, 0);
ActuatorController::setArmSpeeds(0, 0); // Braccia completamente ritirate
ActuatorController::setLegSpeeds(0, 0); // Gambe completamente ritirate
leds.setBrightness(0);
leds.show();
break;
case Emotion::CURIOUS:
ActuatorController::setMotorSpeeds(128, 128);
ActuatorController::setArmSpeeds(90, 90); // Braccia a metà estensione
ActuatorController::setLegSpeeds(90, 90); // Gambe a metà estensione
leds.setBrightness(128);
leds.show();
break;
case Emotion::ANGRY:
ActuatorController::setMotorSpeeds(0, 0);
ActuatorController::setArmSpeeds(0, 0); // Braccia completamente ritirate
ActuatorController::setLegSpeeds(0, 0); // Gambe completamente ritirate
leds.setBrightness(255);
leds.show();
break;
}
}
// Funzione di setup
void setup() {
Serial.begin(115200);
pinMode(Pin::BUZZER, OUTPUT);
// Inizializzazione dei servomotori
ActuatorController::initialize();
// Inizializzazione sensori
mpu.begin();
lidar.begin();
FastLED.addLeds<WS2812, Pin::LED, RGB>(leds);
// Configurazione della rete
WiFi.begin(Network::WIFI_SSID, Network::WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
mqttClient.setServer(Network::MQTT_SERVER, 1883);
mqttClient.setCallback(handleMQTTMessage);
// Configurazione di TensorFlow Lite
model = tflite::GetModel(model_data); // Assumi che `model_data` sia definito
opResolver.AddBuiltin(tflite::BuiltinOperator_ADD, tflite::ops::micro::Register_ADD());
TensorFlowLite::tensorArena.allocate(TENSOR_ARENA_SIZE);
interpreter = new tflite::MicroInterpreter(model, opResolver, TensorFlowLite::tensorArena, &TensorFlowLite::errorReporter);
// Sincronizzazione oraria
ntpClient.begin();
}
// Funzione di loop
void loop() {
if (!mqttClient.connected()) {
reconnectToMQTT();
}
mqttClient.loop();
// Funzioni di controllo
advancedControl();
inferTensorFlowLite();
avoidObstacles();
updateEmotion();
}
vorrei avere un vosto parere