Archivi tag: Arduino UNO R3

Esercitazione 3 – Scheduler cooperativo con tre task e supervisione dei tempi

Allenamento per l’esame di maturità
Percorso di laboratorio con Arduino per studenti di quinta ITIS

Obiettivo didattico

Organizzare il programma come scheduler cooperativo con tre task indipendenti: acquisizione analogica, lampeggio di stato e trasmissione seriale periodica. L’attività mostra come il loop() possa diventare un piccolo supervisore software.

Materiali suggeriti

  • Arduino UNO R3 o UNO R4;
  • 1 potenziometro;
  • 2 LED;
  • 2 resitori (per i LED);
  • breadboard;
  • cavetti jumper.

Schema di collegamento

Richiamo teorico

In un sistema embedded semplice non si usa un vero sistema operativo, ma si può costruire uno scheduler cooperativo con millis(). Ogni task possiede il proprio intervallo e il proprio istante dell’ultima esecuzione. Il loop() controlla se ciascun task è pronto e lo richiama.

Schema logico dell’attività

Il programma inizializza i timer dei tre task. Nel loop legge il tempo corrente e verifica uno dopo l’altro se è il momento di eseguire il task di acquisizione, quello di segnalazione e quello di stampa seriale. Se il tempo non è scaduto, passa al controllo successivo.

Diagramma di flusso

Diagramma di flusso Mermaid

flowchart TD
    A[Inizio] --> B[Configura pin, seriale e timer]
    B --> C[Leggi tempo attuale]
    C --> D{Task acquisizione pronto?}
    D -- Sì --> E[Esegui acquisizione]
    D -- No --> F{Task LED pronto?}
    E --> F
    F -- Sì --> G[Commuta LED di stato]
    F -- No --> H{Task seriale pronto?}
    G --> H
    H -- Sì --> I[Invia dati in seriale]
    H -- No --> J[Ritorna al loop]
    I --> J
    J --> C

Programma

/*
  Prof. Maffucci Michele
  Esercizio 3: scheduler cooperativo con tre task indipendenti
*/

const int PIN_SENSORE = A0;
const int PIN_LED_STATO = 8;
const int PIN_LED_SOGLIA = 9;

// ---------------------------
// Intervalli dei tre task
// ---------------------------
const unsigned long PERIODO_ACQUISIZIONE = 50;
const unsigned long PERIODO_LED = 300;
const unsigned long PERIODO_SERIALE = 500;

// ---------------------------
// Istanti ultima esecuzione
// ---------------------------
unsigned long ultimoTaskAcquisizione = 0;
unsigned long ultimoTaskLed = 0;
unsigned long ultimoTaskSeriale = 0;

// ---------------------------
// Variabili condivise
// ---------------------------
int valoreGrezzo = 0;
float tensione = 0.0;
bool statoLed = false;

void setup() {
  pinMode(PIN_LED_STATO, OUTPUT);
  pinMode(PIN_LED_SOGLIA, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // Il loop assume il ruolo di piccolo scheduler.
  unsigned long adesso = millis();

  // ---------------------------
  // Task 1: acquisizione
  // ---------------------------
  if ((adesso - ultimoTaskAcquisizione) >= PERIODO_ACQUISIZIONE) {
    ultimoTaskAcquisizione = adesso;
    taskAcquisizione();
  }

  // ---------------------------
  // Task 2: LED di stato
  // ---------------------------
  if ((adesso - ultimoTaskLed) >= PERIODO_LED) {
    ultimoTaskLed = adesso;
    taskLed();
  }

  // ---------------------------
  // Task 3: seriale
  // ---------------------------
  if ((adesso - ultimoTaskSeriale) >= PERIODO_SERIALE) {
    ultimoTaskSeriale = adesso;
    taskSeriale();
  }
}

// ----------------------------------------------------------
// Legge il sensore e calcola una tensione equivalente.
// ----------------------------------------------------------
void taskAcquisizione() {
  valoreGrezzo = analogRead(PIN_SENSORE);

  // Conversione esplicita ADC -> tensione.
  tensione = (valoreGrezzo * 5.0) / 1023.0;

  // Uso della misura per attivare un LED di soglia.
  if (tensione >= 2.50) {
    digitalWrite(PIN_LED_SOGLIA, HIGH);
  } else {
    digitalWrite(PIN_LED_SOGLIA, LOW);
  }
}

// ----------------------------------------------------------
// Task di segnalazione periodica.
// ----------------------------------------------------------
void taskLed() {
  if (statoLed == false) {
    statoLed = true;
    digitalWrite(PIN_LED_STATO, HIGH);
  } else {
    statoLed = false;
    digitalWrite(PIN_LED_STATO, LOW);
  }
}

// ----------------------------------------------------------
// Task di comunicazione seriale.
// ----------------------------------------------------------
void taskSeriale() {
  Serial.print("ADC = ");
  Serial.print(valoreGrezzo);
  Serial.print("  Tensione = ");
  Serial.print(tensione, 2);
  Serial.println(" V");
}

Continua a leggere

EduRobot 4WD – Bluetooth

Alcuni lettori hanno notato nella lezione in cui ho condiviso i sorgenti per la stampa 3D del robot, che la scheda motori utilizzata è una Adafruit Motor Shield V01 e mi è stato fatto notare che esiste la V02 della scheda, quindi perché ho usato la versione precedente? La risposta non è tecnica ma economica, ho acquistato ad un prezzo interessante, su uno store cinese, una grande quantità di queste schede che poi ho usato per i miei corsi. Ovviamente nulla vieta che voi possiate utilizzare una qualsiasi altra scheda, la logica di programmazione è la medesima, ma certamente varieranno il nome delle istruzioni che controllano il motore, se avete necessità contattatemi.

Lista componenti

  • N. 1 Arduino UNO R3
  • N. 1 Adafruit Motor Shield V01
  • Modulo Bluetooth HC05
  • N. 4 Motori DC 6V
  • N. 4 Ruote

Di seguito trovate i collegamenti elettrici effettuati e il primo sketch di esempio con cui parto per svolgere le successive esercitazioni. Per gli allievi e i docenti che si iscriveranno ai miei corsi darò ulteriori esempi e spiegazioni.

Lo shield per il controllo motori può gestire fino a 4 motori DC in entrambe le direzioni, ciò vuol dire che possono essere azionati sia in avanti che all’indietro. La velocità può anche essere variata con incrementi dello 0,5% utilizzando PWM integrato sulla scheda, ciò permetterà un movimento uniforme e non brusca del robot.

Il ponte H presente sulla scheda può pilotare carichi NON superiori ai 0,6A o che hanno picchi di richiesta corrente NON superiori a 1,2A, quindi utilizzate questa scheda per piccoli motori, i classici motori gialli da 6V vanno più che bene.

Collegamento motori allo shield Arduino Motor Driver

Come indicato nell’immagine che segue è molto semplice:
– saldate due cavi al motorino (in commercio trovate motori con fili saldati)
– collegate i motori ai morsetti: M1, M2, M3 o M4.

Collegamento scheda Bluetooth HC-05 allo shield Arduino Motor Driver

Come sicuramente saprete, il modulo Bluetooth HC-05 permette di convertire una porta seriale UART in una porta Bluetooth e la utilizzeremo per inviare su seriale i caratteri selezionati da una specifica app Android, per comandare direzione e velocità dei motori del robot.

I collegamenti sono:

HC05 <-> Arduino Motor Driver
RX - Pin 1
TX - Pin 0
G - GND
V - +5V

Orientamento ruote.

Collegamento motori M1 e M2.

Collegamento motori M3 e M4.

Modulo Bluetooth HC-05.

Connessione dei pin RX e TX del modulo Bluetooth HC-05 alla seriale di Arduino (pin 0 e pin 1).

Alimentazione del modulo Bluetooth HC-05 attraverso lo shield.

Alimentazione dello shield.

Continua a leggere