Main Content

Questa pagina è stata tradotta con la traduzione automatica. Fai clic qui per vedere l'ultima versione in inglese.

Controllo remoto del sensore tramite Pubblica e Iscriviti MQTT sicuro

Questo esempio mostra come utilizzare l'architettura di pubblicazione e sottoscrizione MQTT in ThingSpeak. Il protocollo MQTT è un sistema di messaggistica dei dispositivi a basso costo. Utilizzando MQTT, iscriviti al campo 1 di un canale di controllo. Quando aggiorni il canale di controllo, il valore pubblicato viene inviato al tuo dispositivo. Il servo ruota all'angolo specificato. Il dispositivo misura la potenza della rete e aggiorna il canale di archiviazione. I commenti nel codice indicano come adattare questo esempio per una connessione non protetta.

Hardware supportato

  • ESP8266, NodeMCU, WeMOS

  • Arduino MKR1000

  • Arduino Uno, Mega, Due o Leonardo con connessione di rete wireless

  • Particle Photon (con leggero codice e modifiche schematiche)

L'esempio è progettato per funzionare solo con pochi componenti aggiuntivi, vale a dire un singolo servomotore. Si utilizza l'antenna Wi-Fi integrata per effettuare misurazioni della potenza Wi-Fi.

Queste immagini mostrano l'output del canale campione dal canale di archiviazione. Il campo 1 memorizza l'angolo del servomotore impostato dal canale di controllo e il campo 2 mostra il valore di potenza Wi-Fi misurato.

L'analisi dei dati mostra che l'orientamento dell'hardware WeMOS ha un effetto direzionale sulla potenza del segnale misurato.

Prerequisiti

1) Creare un canale ThingSpeak per il controllo dell'iscrizione come mostrato in Collect Data in a New Channel. Il canale di sottoscrizione contiene l'angolo per il servomotore. Quando l'angolo del servomotore viene aggiornato, il dispositivo registrato riceve l'angolo come messaggio MQTT. Il dispositivo imposta l'angolo del servo e misura la nuova potenza della rete wireless a quell'angolo.

2) Creare un altro canale ThingSpeak per i dati pubblicati. Il canale di pubblicazione registra l'angolo impostato e i dati sulla potenza del segnale.

3) Nella visualizzazione Impostazioni canale abilitare i campi 1 e 2 per il canale di pubblicazione. Per distinguere tra i campi, assegnare a ciascun campo un nome descrittivo.

4) Annotare le chiavi API di lettura e scrittura nella scheda Chiavi API nella vista Impostazioni canale (cerchiata nell'immagine).

5) Crea un dispositivo MQTT facendo clic su Dispositivi > MQTT nella parte superiore della pagina, quindi su Aggiungi un nuovo dispositivo. Quando configuri il dispositivo, autorizza entrambi i canali per la pubblicazione e l'iscrizione. Per i dettagli, vedere Crea un dispositivo MQTT ThingSpeak.

6) Mentre aggiungi il nuovo dispositivo, fai clic su Scarica credenziali > Arduino (mqtt_secrets.h). Conserva questo file segreto scaricato per l'accesso nella sezione Codice di seguito.

Hardware richiesto

  • WeMOS D1 Mini, oppure uno dei seguenti dispositivi con modifiche alle librerie utilizzate: NodeMCU, ESP8266-01, ESP8266-04, ESP8266-12, ESP8266-12E, Arduino® MKR1000 o altro Arduino con connessione di rete Ethernet o wireless

  • Servomotore (ad esempio Futaba S3003)

  • Cavi di avviamento (almeno 3)

  • Cavo USB

Schema e collegamenti

1) Collegare D5 sul WeMOS D1 Mini alla linea del segnale del servo.

2) Collegare il filo di terra del servo alla terra sulla scheda WeMOS.

3) Collegare l'alimentazione del servo a 3,3 V. In alcuni casi, l'utilizzo diretto di 5 V può sovraccaricare il limite di alimentazione USB.

Programma il tuoArduino

Usa l'IDE Arduino per programmare il tuo dispositivo. Puoi scaricare l'ultimo IDE Arduino here.

1) Aggiungi il pacchetto scheda ESP8266:

A. Sotto File > Preferenze, inserisci https://arduino.esp8266.com/stable/package_esp8266com_index.json in Ulteriori URL del Board Manager.

B. Seleziona Strumenti > Schede > Gestione schede. Inserisci ESP8266 nella barra di ricerca e installa il pacchetto.

2) Modificare la dimensione del pacchetto consentita.

A. Passare alla cartella con il file di intestazione della libreria secondaria pub, generalmente Documents\Arduino\libraries\PubSubClient\src.

B. Modificare PubSubClient.h to c modifica la dimensione massima del pacchetto a 4096. Una volta completata, la riga dovrebbe essere:

#define MQTT_MAX_PACKET_SIZE 4096

3) Creare l'applicazione:

A. Apri una nuova finestra nell'IDE di Arduino e salva il file.

B. Aggiungi il codice fornito nella sezione Codice.

C. Assicurati di modificare le informazioni sulla rete wireless e gli ID canale nel codice.

4) Aggiungi librerie e file segreti allo schizzo:

A. Se non sono già presenti, aggiungi le seguenti librerie al gestore delle librerie selezionando Schizzo > Includi libreria > Gestisci librerie. Per ogni libreria cerca il suo nome e seleziona Installa.

  • PubSubClient

  • ESP8266Wifi

  • servo

B. Aggiungi il file mqtt_secrets.h .

Metti alla prova il tuo dispositivo

Dopo aver caricato correttamente il programma, puoi monitorare l'output utilizzando il monitor seriale. Carica un valore sul tuo canale di controllo ThingSpeak compreso tra 0 e 175. Puoi copiare il formato della richiesta GET dalla scheda Chiavi API o modificare questo testo con la tua chiave API di scrittura. Inserisci ciascun URL direttamente nella barra degli indirizzi del tuo browser, cambiando la TUA CHIAVE API DI SCRITTURA con la chiave API di scrittura per il tuo canale.

https://api.thingspeak.com/update?api_key=YOUR_WRITE_API_KEY&field1=ANGLE_VALUE

Il dispositivo pubblica l'angolazione e la potenza del segnale Wi-Fi sul canale di archiviazione ogni volta che pubblichi sul canale di iscrizione. Assicurati che il valore dell'angolo sia compreso tra 0 e 175.

Codice

1) Includere le librerie richieste e definire i campi dati:

#include <PubSubClient.h>
#include <WiFiClientSecure.h>                         // Needed only if using secure connection.
#include <ESP8266WiFi.h>
#include <Servo.h> 
#include "mqtt_secrets.h"
#define ANGLE_FIELD 0   
#define DATA_FIELD 1                                  // Data field to post the signal strength to.

2) Definire e inizializzare le variabili. Assicurati di modificare le informazioni sulla rete wireless, l'ID del canale e le credenziali. Trova l'ID del tuo canale nella parte superiore della pagina principale del tuo canale.

char ssid[] = "YOUR_SSID";                   // Change to your network SSID (name).
char pass[] = "YOUR_WIFI_PASSWORD";          // Change to your network password.
const char* server = "mqtt3.thingspeak.com";
char mqttUserName[] = SECRET_MQTT_USERNAME;  // Change to your MQTT device username.    
char mqttPass[] = SECRET_MQTT_PASSWORD;      // Change to your MQTT device password.
char clientID[] = SECRET_MQTT_CLIENT_ID;     // Change to your MQTT device clientID.
long readChannelID = 85;
long writeChannelID = 86;

// Here's how to get ThingSpeak server fingerprint: https://www.a2hosting.com/kb/security/ssl/a2-hostings-ssl-certificate-fingerprints
const char* thingspeak_server_fingerprint = "27 18 92 dd a4 26 c3 07 09 b9 7a e6 c5 21 b9 5b 48 f7 16 e1";

// WiFiClient client;                                 // Initialize the Wi-Fi client library. Uncomment for nonsecure connection.
WiFiClientSecure client;                              // Uncomment for secure connection.  
PubSubClient mqttClient( client );                    // Initialize the PuBSubClient library.
Servo myservo;  // Create servo object to control a servo .

int fieldsToPublish[8]={1,1,0,0,0,0,0,0};             // Change to allow multiple fields.
float dataToPublish[8];                               // Holds your field data.
int changeFlag=0;                                     // Let the main loop know there is new data to set.
int servo_pos=0;                                      // Servo position

3) Definire i prototipi di funzione in questo codice.

//  
// Prototypes
//

// Handle messages from MQTT subscription.
void mqttSubscriptionCallback(char* topic, byte* payload, unsigned int length);  

// Generate a unique client ID and connect to MQTT broker.
void mqttConnect();  

// Subscribe to a field or feed from a ThingSpeak channel.
int mqttSubscribe( long subChannelID,int field, int unSub);

// Publish messages to a channel feed.

// Connect to a given Wi-Fi SSID.
int connectWifi();

// Measure the Wi-Fi signal strength.
void updateRSSIValue();

4) Inizializzare i pin per input e output, avviare il monitor seriale e inizializzare il client MQTT nella routine setup .

void setup() {
Serial.begin( 115200 );
Serial.println( "Start" );
int status = WL_IDLE_STATUS; // Set temporary Wi-Fi status.
       
    connectWifi();                                        // Connect to Wi-Fi network.
    // mqttClient.setServer( server, 1883 );              // Set the MQTT broker details, nonsecure port. Uncomment for nonsecure connection.
    mqttClient.setServer( server, 8883 );                 // Set the MQTT broker details, secure port. Uncomment for secure connection.
    mqttClient.setCallback( mqttSubscriptionCallback );   // Set the MQTT message handler function.
    myservo.attach(14);                                   // Attach the servo on GIO2 to the servo object. 
    myservo.write(90);                                    // Start in the middle.
}

5) Ogni volta che viene eseguito il ciclo principale, verificare se i dati dell'abbonamento MQTT sono disponibili per l'elaborazione. Quindi impostare la posizione del servo in modo che corrisponda ai dati. Assicurati che i client wireless e MQTT siano attivi e mantengano una connessione al server client.

void loop() {
    
    if (WiFi.status() != WL_CONNECTED) {
        connectWifi();
    }
    
    if (!mqttClient.connected())
    {
       
       mqttConnect(); // Connect if MQTT client is not connected.
        
         if(mqttSubscribe( readChannelID,1,0 )==1 ){
                Serial.println( " Subscribed " );
            }
    }
    
    mqttClient.loop(); // Call the loop to maintain connection to the server.                         

    if ((servo_pos>175)||(servo_pos<0)){
    servo_pos=0;
    }
   
    if (changeFlag){
      
        changeFlag=0;
        myservo.write(servo_pos);
        dataToPublish[ANGLE_FIELD]=servo_pos;
        delay(1100);                       // Wait for ThingSpeak to publish.
        Serial.println( "Servo value " + String( servo_pos ) );
        mqttPublish( writeChannelID, dataToPublish, fieldsToPublish );
    }
    
    delay(1);
}

6) Utilizzare la funzione mqttSubscriptionCallback per gestire i messaggi MQTT in entrata. Il programma viene eseguito in modo più fluido se il ciclo principale esegue i passaggi di elaborazione anziché il callback. In questa funzione, utilizzare i flag per causare modifiche nel ciclo principale.

/**
 * Process messages received from subscribed channel via MQTT broker.
 *   topic - Subscription topic for message.
 *   payload - Field to subscribe to. Value 0 means subscribe to all fields.
 *   mesLength - Message length.
 */

void mqttSubscriptionCallback( char* topic, byte* payload, unsigned int mesLength ) {
    
    char p[mesLength + 1];
    memcpy( p, payload, mesLength );
    p[mesLength] = NULL;
    Serial.print( "Answer: " );
    Serial.println( String(p) );
    servo_pos=atoi( p );
    changeFlag=1;
}

7) Utilizzare la funzione MQTTConnect per impostare e mantenere una connessione all'MQTT.

void mqttConnect()
{
    // Loop until connected.
    while ( !mqttClient.connected() )
    {
      Serial.println(String( mqttUserName)+ " , " + mqttPass + " , " + clientID);
   
        // Connect to the MQTT broker.
        Serial.print( "Attempting MQTT connection..." );
        if ( mqttClient.connect( clientID, mqttUserName, mqttPass ) )
        {
            Serial.println( "Connected with Client ID:  " + String( clientID ) + " User "+ String( mqttUserName ) + " Pwd "+String( mqttPass ) );
           
        } else
        {
            Serial.print( "failed, rc = " );
            // See https://pubsubclient.knolleary.net/api.html#state for the failure code explanation.
            Serial.print( mqttClient.state() );
            Serial.println( " Will try again in 5 seconds" );
            delay( 5000 );
        }
    }
}

8) Utilizzare mqttSubscribe per ricevere aggiornamenti dal campo di controllo LED. In questo esempio ti iscrivi a un campo, ma puoi anche utilizzare questa funzione per iscriverti all'intero feed del canale. Chiama la funzione con field = 0 per iscriverti all'intero feed.

/**
 * Subscribe to fields of a channel.
 *   subChannelID - Channel to subscribe to.
 *   field - Field to subscribe to. Value 0 means subscribe to all fields.
 *   readKey - Read API key for the subscribe channel.
 *   unSub - Set to 1 for unsubscribe.
 */
 
int mqttSubscribe( long subChannelID, int field, int unsubSub ){
    String myTopic;
    
    // There is no field zero, so if field 0 is sent to subscribe to, then subscribe to the whole channel feed.
    if (field==0){
        myTopic="channels/"+String( subChannelID )+"/subscribe";
    }
    else{
        myTopic="channels/"+String( subChannelID )+"/subscribe/fields/field"+String( field );
    }
    
    Serial.println( "Subscribing to " +myTopic );
    Serial.println( "State= " + String( mqttClient.state() ) );

    if ( unsubSub==1 ){
        return mqttClient.unsubscribe(myTopic.c_str());
    }
    return mqttClient.subscribe( myTopic.c_str() ,0 );
}

9) La funzione mqttUnsubscribe non è utilizzata nel codice, ma è possibile utilizzarla per terminare un abbonamento.

/**
 * Unsubscribe channel
 *   subChannelID - Channel to unsubscribe from.
 *   field - Field to unsubscribe subscribe from. The value 0 means subscribe to all fields.
 *   readKey - Read API key for the subscribe channel.
 */

int mqttUnSubscribe(long subChannelID,int field,char* readKey){
    String myTopic;
    
    if (field==0){
         myTopic="channels/"+String( subChannelID )+"/subscribe";
    }
    else{
        myTopic="channels/"+String( subChannelID )+"/subscribe/fields/field"+String( field );
    }
    return mqttClient.unsubscribe( myTopic.c_str() );   
}

10) Utilizza la funzione mqttPublish per inviare i dati RSSI sull'angolo e Wi-Fi a un canale ThingSpeak .

/**
 * Publish to a channel
 *   pubChannelID - Channel to publish to.
 *   pubWriteAPIKey - Write API key for the channel to publish to.
 *   dataArray - Binary array indicating which fields to publish to, starting with field 1.
 *   fieldArray - Array of values to publish, starting with field 1.
 */

void mqttPublish(long pubChannelID, float dataArray[], int fieldArray[]) {
    int index=0;
    String dataString="";
    
    updateRSSIValue();  // Make sure the stored value is updated.
    
    // 
    while (index<8){
        
        // Look at the field array to build the posting string to send to ThingSpeak.
        if (fieldArray[ index ]>0){
          
            dataString+="&field" + String( index+1 ) + "="+String( dataArray [ index ] );
        }
        index++;
    }
    
    Serial.println( dataString );
    
    // Create a topic string and publish data to ThingSpeak channel feed.
     String topicString ="channels/" + String( pubChannelID ) + "/publish";
    mqttClient.publish( topicString.c_str(), dataString.c_str() );
    Serial.println( "Published to channel " + String( pubChannelID ) );
}

11) Connetti il ​​tuo dispositivo ad una rete wireless utilizzando la funzione connectWiFi .

int connectWifi()
{
    while ( WiFi.status() != WL_CONNECTED ) {
        WiFi.begin( ssid, pass );
        delay( 8500 );
        Serial.println( "Connecting to Wi-Fi" ); 
    }
    Serial.println( "Connected" );
    client.setFingerprint(thingspeak_server_fingerprint);  // Comment this line if using nonsecure connection.
}

12) Utilizza la funzione updateRSSIValue per leggere la potenza del segnale per la rete a cui sei attualmente connesso.

void updateRSSIValue(){

   long rssi = WiFi.RSSI();  
   Serial.print( "RSSI:" );
   Serial.println(rssi);
   dataToPublish[ DATA_FIELD ]=float( rssi );

}

Vedi anche

|

Argomenti complementari