STM32F103を使ってみる

MQTT通信



Ethernet_STMライブラリ+W5x00モジュールを使ったMQTT通信を紹介します。
こちらで紹介している ArduinoのMQTTのスケッチを元に、
Publisher/SubscriberともライブラリとTOPICだけを変えて書きこんでみましたがあっさりと動きました。
/*
 MQTT Publish for STM32F103 with W5x000 Module
 
 PIN Connections (Using STM32F103):

   W5x00  -  STM32F103
   ---------------------
   VCC    -  3.3V
   GND    -  GND
   SS     -  Pin PA4
   SCLK   -  Pin PA5
   MISO   -  Pin PA6
   MOSI   -  Pin PA7
   RST    -  PullUp
*/

#include <SPI.h>
#include <Ethernet_STM.h>   // https://github.com/rogerclarkmelbourne/Arduino_STM32
#include <PubSubClient.h> // https://github.com/knolleary/pubsubclient

#define INTERVAL        30 // 30秒毎にPublish
//#define MQTT_SERVER     "broker.hivemq.com"
//#define MQTT_SERVER     "iot.eclipse.org"
#define MQTT_SERVER     "192.168.10.40"  // You need change
#define MQTT_PORT       1883
#define MQTT_PUB_TOPIC  "stm32f103/C8T6" // You can change
#define MQTT_WILL_TOPIC "stm32f103/C8T6" // You can change
#define MQTT_WILL_MSG   "I am leaving..." // You can change
#define RUNNING_LED     PB0 // 0: Disable RUNNING_LED

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io
;
#else
#if defined(W5100_ETHERNET_SHIELD)
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x51 };
#else
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x56 };
#endif
#endif


EthernetClient ethClient;
PubSubClient pubsubClient(ethClient);

unsigned long lastTime = 0;
char clientid[30];

#if defined(W5100_ETHERNET_SHIELD)
  char* shield = "W5100";
#else
  char* shield = "W5500";
#endif

void errorDisplay(char* buff) {
  int stat = 0;
  Serial.print("Error:");
  Serial.println(buff);
  while(1) {
    if (RUNNING_LED) {
      digitalWrite(RUNNING_LED,stat);
      stat = !stat;
      delay(100);
    }
  }
}

void connectToServer() {
  int retry = 0; 
  while(1) {
    Serial.print(" Attempting MQTT connection ...");
    if (pubsubClient.connect(clientid,MQTT_WILL_TOPIC,0,0,MQTT_WILL_MSG)) break;
    Serial.println("connect Fail");
    delay(5000);
    retry++;
    if (retry > 100) errorDisplay("connect retry over!!");
  }
  Serial.println("connected");
}


void setup() {
  Serial.begin(9600);
  Serial.print("\n[MQTT Publish for ");
  Serial.print(shield);
  Serial.println("]");
 
  if (RUNNING_LED) {
    pinMode(RUNNING_LED,OUTPUT);
    digitalWrite(RUNNING_LED,LOW);
  }

  // start Ethernet
#if defined(WIZ550io_WITH_MACADDRESS)
  if (Ethernet.begin() == 0) {
#else
  if (Ethernet.begin(mac) == 0) {
#endif 
    errorDisplay("Failed to configure Ethernet using DHCP");
  }

  Serial.print("My IP: ");
  Serial.println(Ethernet.localIP());
  Serial.print("Netmask: ");
  Serial.println(Ethernet.subnetMask());
  Serial.print("GW IP: ");
  Serial.println(Ethernet.gatewayIP());
  Serial.print("DNS IP: ");
  Serial.println(Ethernet.dnsServerIP());

#if defined(WIZ550io_WITH_MACADDRESS)
  byte mac_address[6] ={0,};
  W5100.getMACAddress(mac_address);
  Serial.print("MAC: ");
  for(int i = 0; i < 6; i++) {
    Serial.print("0x");
    Serial.print(mac_address[i],HEX);
    Serial.print(" ");
  }
  Serial.println();
#endif

  pubsubClient.setServer(MQTT_SERVER, MQTT_PORT);

  IPAddress ip = Ethernet.localIP();
  Serial.print(ip[0]);
  Serial.print(".");
  Serial.print(ip[1]);
  Serial.print(".");
  Serial.print(ip[2]);
  Serial.print(".");
  Serial.println(ip[3]);
  sprintf(clientid,"STM32-%03d",(int)ip[3]);
  Serial.print("clientid=");
  Serial.println(clientid);

#if 0
  // Attempt to connect
  Serial.print("Attempting MQTT connection...");
  if (!pubsubClient.connect(clientid,MQTT_WILL_TOPIC,0,0,MQTT_WILL_MSG)) {
    errorDisplay("connect Fail");
  }
  Serial.println("connected");
#endif

  lastTime = millis();
 
}

void loop(){
  static int counter=0;
  static int value = 0;
  static int running_state = 1;
  char payload[50];

  if (Serial.available() > 0) {
    char inChar = Serial.read();
    Serial.println("KeyIn");
    pubsubClient.disconnect();
    Serial.println("Publish end");
    while(1) { }
  }

  if (!pubsubClient.connected()) {
    connectToServer();
    snprintf (payload, 75, "clientid:%s shield:%s connected...",clientid,shield);
    if (!pubsubClient.publish(MQTT_PUB_TOPIC, payload)) {
       errorDisplay("publish fail");
    }
  }

  pubsubClient.loop();

  long now = millis();
  if (now - lastTime > 1000) {
    lastTime = now;
    counter++;
    if (RUNNING_LED) digitalWrite(RUNNING_LED,running_state);
    running_state = !running_state;
    if (counter > INTERVAL) {
      ++value;
//      snprintf (payload, 75, "hello world!! I'm STM32F103-%s-%s #%ld",clientid,shield,value);
      snprintf (payload, 75, "hello world!! I'm %s-%s #%ld",clientid,shield,value);
      Serial.print("Publish Topioc: ");
      Serial.println(MQTT_PUB_TOPIC);
      Serial.print("Publish Payload: ");
      Serial.println(payload);
      if (!pubsubClient.publish(MQTT_PUB_TOPIC, payload)) {
        errorDisplay("publish fail");
      }
      counter=0;
    }
  } 
}


W5100とW5500を使って2台のSTMに書き込んでみましたが、どちらも安定して動きます。




Ethernet_STMライブラリ+W5x00モジュールを使ったSubscribe側スケッチは以下のようになります。
/*
 MQTT Subscribe for STM32F103 with W5x000 Module
 
 PIN Connections (Using STM32F103):

   W5x00  -  STM32F103
   ---------------------
   VCC    -  3.3V
   GND    -  GND
   SS     -  Pin PA4
   SCLK   -  Pin PA5
   MISO   -  Pin PA6
   MOSI   -  Pin PA7
   RST    -  PullUp
*/

#include <SPI.h>
#include <Ethernet_STM.h>   // https://github.com/rogerclarkmelbourne/Arduino_STM32
#include <PubSubClient.h> // https://github.com/knolleary/pubsubclient

#define MQTT_SERVER     "192.168.10.40"  // You need change
#define MQTT_PORT       1883
#define MQTT_SUB_TOPIC  "stm32f103/#"
#define MQTT_WILL_TOPIC "stm32f103/C8T6" // You can change
#define MQTT_WILL_MSG   "I am leaving..." // You can change
#define RUNNING_LED     PB1 // 0: Disable RUNNING_LED

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io
;
#else
#if defined(W5100_ETHERNET_SHIELD)
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0x51 };
#else
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFF, 0x55 };
#endif
#endif


EthernetClient ethClient;
PubSubClient pubsubClient(ethClient);

char clientid[30];

#if defined(W5100_ETHERNET_SHIELD)
  char* shield = "W5100";
#else
  char* shield = "W5500";
#endif

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] [");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println("]");
}

void errorDisplay(char* buff) {
  int stat = 0;
  Serial.print("Error:");
  Serial.println(buff);
  while(1) {
    digitalWrite(RUNNING_LED,stat);
    stat = !stat;
    delay(100);
  }
}

void connectToServer() {
  int retry = 0; 
  while(1) {
    Serial.print("Attempting MQTT connection ...");
    if (pubsubClient.connect(clientid,MQTT_WILL_TOPIC,0,0,MQTT_WILL_MSG)) break;
    Serial.println("connect Fail");
    delay(5000);
    retry++;
    if (retry > 100) errorDisplay("connect retry over!!");
  }
  Serial.println("connected");

  Serial.print("Attempting MQTT subscribe ...");
  if (!pubsubClient.subscribe(MQTT_SUB_TOPIC)) {
    errorDisplay("subscribe Fail");
  }
  Serial.println("subscrobed");
 
}

void setup() {
  Serial.begin(9600);
  Serial.println("\n[MQTT Subscribe for ");
  Serial.print(shield);
  Serial.println("]");
 
  if (RUNNING_LED) {
    pinMode(RUNNING_LED,OUTPUT);
    digitalWrite(RUNNING_LED,LOW);
  }

  // start Ethernet
#if defined(WIZ550io_WITH_MACADDRESS)
  if (Ethernet.begin() == 0) {
#else
  if (Ethernet.begin(mac) == 0) {
#endif 
    errorDisplay("Failed to configure Ethernet using DHCP");
  }

  Serial.print("My IP: ");
  Serial.println(Ethernet.localIP());
  Serial.print("Netmask: ");
  Serial.println(Ethernet.subnetMask());
  Serial.print("GW IP: ");
  Serial.println(Ethernet.gatewayIP());
  Serial.print("DNS IP: ");
  Serial.println(Ethernet.dnsServerIP());

#if defined(WIZ550io_WITH_MACADDRESS)
  byte mac_address[6] ={0,};
  W5100.getMACAddress(mac_address);
  Serial.print("MAC: ");
  for(int i = 0; i < 6; i++) {
    Serial.print("0x");
    Serial.print(mac_address[i],HEX);
    Serial.print(" ");
  }
  Serial.println();
#endif

  pubsubClient.setServer(MQTT_SERVER, MQTT_PORT);
  pubsubClient.setCallback(callback);

  IPAddress ip = Ethernet.localIP();
  sprintf(clientid,"STM32-%03d",(int)ip[3]);
  Serial.print("clientid=");
  Serial.println(clientid);

  connectToServer();
#if 0
  // Attempt to connect
  Serial.print("Attempting MQTT connection...");
  if (!pubsubClient.connect(clientid,MQTT_WILL_TOPIC,0,0,MQTT_WILL_MSG)) {
    errorDisplay("connect Fail");
  }
  Serial.println("connected");
  if (!pubsubClient.subscribe(MQTT_SUB_TOPIC)) {
    errorDisplay("subscribe Fail");
  }
#endif
}

void loop() {
  if (!pubsubClient.connected()) {
    connectToServer();
  }
  pubsubClient.loop();
}

3台目のSTM32で動かしてみました。


続く...