Nota

Ciao, benvenuto nella comunità SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts su Facebook! Approfondisci Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

Perché unirsi?

  • Supporto esperto: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra comunità e del nostro team.

  • Impara e condividi: Scambia suggerimenti e tutorial per migliorare le tue competenze.

  • Anteprime esclusive: Ottieni accesso anticipato agli annunci di nuovi prodotti e anteprime.

  • Sconti speciali: Goditi sconti esclusivi sui nostri prodotti più recenti.

  • Promozioni e giveaway festivi: Partecipa a giveaway e promozioni durante le festività.

👉 Pronto a esplorare e creare con noi? Clicca [Qui] e unisciti oggi stesso!

3.1.5 Indicatore di Batteria (MCP3008)

Nota

_images/mcp3008_and_adc0834.jpg

A seconda della versione del kit, verifica se possiedi ADC0834 o MCP3008 e procedi con la sezione corrispondente.

Introduzione

In questo progetto, realizzeremo un dispositivo indicatore di batteria che può mostrare visivamente il livello della batteria sul LED Bargraph.

Avvertimento

Non utilizzare componenti della batteria che superino i 3,3 V per evitare sovraccarichi che potrebbero danneggiare il chip o il Raspberry Pi.

Componenti necessari

Per questo progetto, abbiamo bisogno dei seguenti componenti.

_images/list2_Battery_Indicator.png

Schema elettrico

T-Board Name

fisico

wiringPi

BCM

SPICE0

Pin 24

10

8

SPIMOSI

Pin 19

12

10

SPIMISO

Pin 21

13

9

SPISCLK

Pin 23

14

11

GPIO25

Pin 22

6

25

GPIO12

Pin 32

26

12

GPIO16

Pin 36

27

16

GPIO20

Pin 38

28

20

GPIO21

Pin 40

29

21

GPIO5

Pin 29

21

5

GPIO6

Pin 31

22

6

GPIO13

Pin 33

23

13

GPIO19

Pin 35

24

19

GPIO26

Pin 37

25

26

_images/schematic_battery_indicator_mcp3008.png

Procedure sperimentali

Passo 1: Montare il circuito.

_images/july24_3.1.5_battery_indicator_mcp3008.png

Per utenti linguaggio C

Passo 2: Accedere alla cartella del codice.

cd ~/davinci-kit-for-raspberry-pi/c/3.1.5-2/

Passo 3: Compilare il codice.

gcc 3.1.5_BatteryIndicator.c -lwiringPi

Passo 4: Eseguire il file eseguibile.

sudo ./a.out

Dopo l’esecuzione del programma, collega separatamente un filo dal 3° pin di MCP3008 e un filo dal GND ai due poli della batteria. Potrai vedere il LED corrispondente sul LED Bargraph accendersi per mostrare il livello della batteria (intervallo di misurazione: 0-5V).

Nota

Se non funziona dopo l’esecuzione, o compare l’errore: «wiringPi.h: No such file or directory», fare riferimento a Installare e Verificare WiringPi.

Codice

#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>

#define SPI_CHANNEL 0
#define SPI_SPEED   1000000  // 1MHz
#define VREF        3.3

int pins[10] = {6, 26, 27, 28, 29, 21, 22, 23, 24, 25};

int read_ADC(int channel)
{
    if (channel < 0 || channel > 7) return -1;

    unsigned char buffer[3];
    buffer[0] = 1;  // Start bit
    buffer[1] = (8 + channel) << 4;  // Single-ended mode
    buffer[2] = 0;

    wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);

    int value = ((buffer[1] & 3) << 8) | buffer[2];
    return value;
}

void LedBarGraph(int value) {
    for (int i = 0; i < 10; i++) {
        if (i < value)
        digitalWrite(pins[i], HIGH);
    else
        digitalWrite(pins[i],LOW);
    }
}

int main(void)
{
    if (wiringPiSetup() == -1) {
        printf("setup wiringPi failed!\n");
        return 1;
    }

    if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
        printf("SPI setup failed!\n");
        return 1;
    }

    for (int i = 0; i < 10; i++) {
        pinMode(pins[i], OUTPUT);
        digitalWrite(pins[i], HIGH);
    }

    while (1) {
        int analogVal = read_ADC(0);  // MCP3008 CH0
        if (analogVal < 0) continue;


        float voltage = analogVal * VREF / 1023.0;
        int level = analogVal * 10 / 1024;
        if (level > 10) level = 10;

        LedBarGraph(level);

        printf("ADC Value: %d\tVoltage: %.2f V\tLevel: %d\n", analogVal, voltage, level);

        delay(200);
    }

    return 0;
}

Spiegazione del codice

int read_ADC(int channel)
{
    if (channel < 0 || channel > 7) return -1;

    unsigned char buffer[3];
    buffer[0] = 1;  // Start bit
    buffer[1] = (8 + channel) << 4;  // Modalità single-ended, CH0~CH7
    buffer[2] = 0;

    wiringPiSPIDataRW(SPI_CHANNEL, buffer, 3);

    int value = ((buffer[1] & 3) << 8) | buffer[2];  // Combina il risultato a 10 bit
    return value;
}

Questa funzione legge valori analogici dal chip MCP3008 tramite SPI. Il parametro channel seleziona uno degli 8 ingressi analogici (CH0–CH7). L’MCP3008 restituisce un valore digitale a 10 bit compreso tra 0 e 1023, che rappresenta la tensione analogica.

void LedBarGraph(int value) {
    for (int i = 0; i < 10; i++) {
        if (i < value)
            digitalWrite(pins[i], HIGH);  // Accende il LED (cablaggio attivo HIGH)
        else
            digitalWrite(pins[i], LOW);   // Spegne il LED
    }
}

Questa funzione controlla una barra LED a 10 segmenti. Ogni LED rappresenta 1/10 dell’intervallo di tensione. I LED vengono accesi in ordine fino al livello specificato.

Nota: Questa versione presuppone che gli anodi dei LED siano collegati ai GPIO e i catodi a GND (attivo HIGH).

int main(void)
{
    if (wiringPiSetup() == -1) {
        printf("setup wiringPi failed!\n");
        return 1;
    }

    if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1) {
        printf("SPI setup failed!\n");
        return 1;
    }

    for (int i = 0; i < 10; i++) {
        pinMode(pins[i], OUTPUT);
        digitalWrite(pins[i], HIGH);  // Inizializza tutti i LED su ON
    }

    while (1) {
        int analogVal = read_ADC(0);  // Legge la tensione su CH0
        if (analogVal < 0) continue;

        float voltage = analogVal * VREF / 1023.0;
        int level = analogVal * 10 / 1024;  // Mappa a livelli 0–10
        if (level > 10) level = 10;

        LedBarGraph(level);  // Mostra il livello sui LED

        printf("ADC Value: %d\tVoltage: %.2f V\tLevel: %d\n", analogVal, voltage, level);

        delay(200);  // Frequenza di aggiornamento: 5 Hz
    }

    return 0;
}

Logica principale del programma:

  • Inizializza wiringPi e la comunicazione SPI.

  • Imposta i pin GPIO come uscite per controllare la barra LED a 10 segmenti.

  • Legge continuamente la tensione analogica tramite MCP3008 (CH0).

  • Converte la lettura in tensione usando VREF = 3.3V.

  • Scala la tensione su un livello da 0 a 10 e accende i LED corrispondenti.

  • Mostra il valore ADC grezzo, la tensione (in volt) e il livello LED sulla console seriale.

Questo progetto funge da indicatore visivo del livello di batteria o da voltmetro analogico.

Per utenti linguaggio Python

Passo 2: Configurare l’interfaccia SPI e installare la libreria spidev (vedere Configurazione SPI per le istruzioni dettagliate). Se hai già completato questi passaggi, puoi saltarli.

Passo 3: Accedere alla cartella del codice.

cd ~/davinci-kit-for-raspberry-pi/python

Passo 4: Eseguire il file.

sudo python3 3.1.5-2_BatteryIndicator.py

Dopo l’esecuzione del programma, collega separatamente un filo dal 3° pin di ADC0834 e un filo dal GND ai due poli della batteria. Potrai vedere il LED corrispondente sul LED Bargraph accendersi per mostrare il livello della batteria (intervallo di misurazione: 0-5V).

Avvertimento

Se appare l’errore RuntimeError: Cannot determine SOC peripheral base address, fare riferimento a Se gpiozero non funziona.

Codice

Nota

Puoi Modificare/Reimpostare/Copiare/Eseguire/Interrompere il codice qui sotto. Ma prima, devi andare nel percorso del codice sorgente come davinci-kit-for-raspberry-pi/python. Dopo aver modificato il codice, puoi eseguirlo direttamente per vedere l’effetto.

#!/usr/bin/env python3

import RPi.GPIO as GPIO
import spidev
import time

# GPIO pins connected to 10 LEDs, ordered from left to right
led_pins = [25, 12, 16, 20, 21, 5, 6, 13, 19, 26]  # BCM numbering

# GPIO setup
GPIO.setmode(GPIO.BCM)
for pin in led_pins:
    GPIO.setup(pin, GPIO.OUT)
    GPIO.output(pin, GPIO.LOW)

# Initialize SPI
spi = spidev.SpiDev()
spi.open(0, 0)  # Bus 0, CE0
spi.max_speed_hz = 1000000  # 1 MHz

# Read value from MCP3008 channel
def read_adc(channel):
    if channel < 0 or channel > 7:
        return -1
    r = spi.xfer2([1, (8 + channel) << 4, 0])
    value = ((r[1] & 0x03) << 8) | r[2]
    return value

# Light up LED bar graph according to value
def led_bar_graph(level):
    for i, pin in enumerate(led_pins):
        if i < level:
            GPIO.output(pin, GPIO.HIGH)
        else:
            GPIO.output(pin, GPIO.LOW)

# Main loop
try:
    while True:
        analog_val = read_adc(0)  # Read from MCP3008 channel 0
        level = int(analog_val * 10 / 1023)
        led_bar_graph(level)
        print(f"ADC: {analog_val}, Level: {level}")
        time.sleep(0.2)

except KeyboardInterrupt:
    pass

finally:
    for pin in led_pins:
        GPIO.output(pin, GPIO.LOW)
    GPIO.cleanup()
    spi.close()

Spiegazione del codice

Questo programma legge la tensione analogica da un MCP3008 ADC e mostra il risultato su un LED Bargraph a 10 LED utilizzando un Raspberry Pi (layout pin BCM).

  1. Importazione moduli

    • RPi.GPIO controlla i pin GPIO del Raspberry Pi.

    • spidev comunica con MCP3008 tramite SPI.

    • time fornisce funzionalità di ritardo/pausa.

    #!/usr/bin/env python3
    
    import RPi.GPIO as GPIO
    import spidev
    import time
    
  2. Configurazione GPIO per i LED

    Viene definita una lista di 10 pin GPIO per il controllo dei LED. Questi pin sono configurati come uscita e inizializzati a LOW (spenti).

    # GPIO pins connected to 10 LEDs, ordered from left to right
    led_pins = [25, 12, 16, 20, 21, 5, 6, 13, 19, 26]  # BCM numbering
    
    GPIO.setmode(GPIO.BCM)
    for pin in led_pins:
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, GPIO.LOW)
    
  3. Inizializzazione SPI

    Inizializza il bus SPI 0 e il chip enable 0 (CE0) per comunicare con MCP3008. La velocità di comunicazione è impostata a 1 MHz.

    spi = spidev.SpiDev()
    spi.open(0, 0)  # Bus 0, CE0
    spi.max_speed_hz = 1000000  # 1 MHz
    
  4. Funzione di lettura ADC

    Legge un valore analogico da un canale specificato di MCP3008 (0–7). La funzione invia un comando SPI di 3 byte e decodifica il risultato a 10 bit.

    def read_adc(channel):
        if channel < 0 or channel > 7:
            return -1
        r = spi.xfer2([1, (8 + channel) << 4, 0])
        value = ((r[1] & 0x03) << 8) | r[2]
        return value
    
  5. Funzione LED Bar Graph

    Accende i LED in base al livello analogico. Se il livello è 7, i primi 7 LED saranno accesi e i restanti spenti.

    def led_bar_graph(level):
        for i, pin in enumerate(led_pins):
            if i < level:
                GPIO.output(pin, GPIO.HIGH)
            else:
                GPIO.output(pin, GPIO.LOW)
    
  6. Ciclo principale

    Legge continuamente l’ingresso analogico dal canale 0, scala il risultato a un valore da 0 a 10 e aggiorna il display LED di conseguenza. Stampa i valori ADC e di livello per il monitoraggio.

    try:
        while True:
            analog_val = read_adc(0)
            level = int(analog_val * 10 / 1023)
            led_bar_graph(level)
            print(f"ADC: {analog_val}, Level: {level}")
            time.sleep(0.2)
    
  7. Pulizia all’uscita

    Quando si preme Ctrl+C, il programma spegne tutti i LED, ripristina lo stato dei GPIO e chiude l’interfaccia SPI.

    except KeyboardInterrupt:
        pass
    
    finally:
        for pin in led_pins:
            GPIO.output(pin, GPIO.LOW)
        GPIO.cleanup()
        spi.close()