B4R Tutorial MQTT controlling 8 relays, WeMos D1 mini WiFi, Android 4G

Discussion in 'B4R Tutorials' started by Peter Simpson, Jun 21, 2017.

  1. Peter Simpson

    Peter Simpson Expert Licensed User

    Here is a short tutorial on how to control an 8 channel relay module via MQTT. Below you will find both the WeMos and Android source codes needed to get started. The relay module is connected to a 74HC595 shift register that in turn is connected by only 3 wires to a WeMos D1 mini based microcontroller. The microcontroller receives MQTT messages/commands through WiFi, the MQTT messages/commands are send by an Android phone through 4G.

    So what is MQTT?
    Well the quick and dirty answer to that question is that MQTT (Message Queuing Telemetry Transport) is an ISO standard, lightweight, low-bandwidth, machine to machine, TCP/IP publish or subscribe messaging protocol which is great for controlling IoT (Internet of Things) devices from over the internet.

    There are plenty of free online MQTT brokers that you can choose from, I personally use a service called CloudMQTT and they can be found right here...
    Please note: For this screen shot I sent all the 'Messages' in plain readable text for testing purposes
    Untitled-2.png

    Send message - Android source code
    Libraries: ByteConverter and jMQTT

    Code:
    Sub Process_Globals
        
    Private MQTT As MqttClient
        
    Private MQTTUser As String = "xxxxxxx"
        
    Private MQTTPassword As String = "_xxxxxxx"
        
    Private MQTTServerURI As String = "tcp://m21.cloudmqtt.com:14925"
        
    Private BC As ByteConverter
    End Sub

    Sub Globals
        
    Private lblStatus As Label
        
    Private SpnTimerMinutes As Spinner
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        
    If FirstTime Then
            
    CallSub(Me, MQTT_Connect)
        
    End If

        
    Activity.LoadLayout("Relay_Switches")

        
    'Populate Spinner With Minutes
        For i = 10 To 60 Step 10
            SpnTimerMinutes.Add(i)
        
    Next
    End Sub

    Sub Activity_Resume
    End Sub

    Sub Activity_Pause (UserClosed As Boolean)
    End Sub

    'Connect to CloudMQTT broker
    Sub MQTT_Connect
            
    Dim ClientId As String = Rnd(0999999999'create a unique id
            MQTT.Initialize("MQTT", MQTTServerURI, ClientId)

            
    Dim ConnOpt As MqttConnectOptions
                ConnOpt.Initialize(MQTTUser, MQTTPassword)
            MQTT.Connect2(ConnOpt)
    End Sub

    Sub MQTT_Connected (Success As Boolean)
        
    If Success = False Then
            
    Log(LastException)
            lblStatus.Text = 
    "Error connecting"
        
    Else
            lblStatus.Text = 
    " - Connected to broker"
            MQTT.Subscribe(
    "drawers/#"0)
        
    End If
    End Sub

    Private Sub MQTT_Disconnected
        lblStatus.Text = 
    " - Disconnected from broker"
    End Sub

    Private Sub MQTT_MessageArrived (Topic As String, Payload() As Byte)
    End Sub

    'PLEASE NOTE:
    'ALTERNATIVELY YOU CAN ALSO CREATED BUTTONS DYNAMICALLY ON THE FLY AND USED A SENDER TO MONITOR BUTTON CLICKS
    Sub ToggleButton0_CheckedChange(Checked As Boolean)
        MQTT.Publish(
    "Relay_0", BC.StringToBytes(Checked, "utf8"))
    End Sub

    Sub ToggleButton1_CheckedChange(Checked As Boolean)
        MQTT.Publish(
    "Relay_1", BC.StringToBytes(Checked, "utf8"))
    End Sub

    Sub ToggleButton2_CheckedChange(Checked As Boolean)
        MQTT.Publish(
    "Relay_2", BC.StringToBytes(Checked, "utf8"))
    End Sub

    Sub ToggleButton3_CheckedChange(Checked As Boolean)
        MQTT.Publish(
    "Relay_3", BC.StringToBytes(Checked, "utf8"))
    End Sub

    Sub ToggleButton4_CheckedChange(Checked As Boolean)
        MQTT.Publish(
    "Relay_4", BC.StringToBytes(Checked, "utf8"))
    End Sub

    Sub ToggleButton5_CheckedChange(Checked As Boolean)
        MQTT.Publish(
    "Relay_5", BC.StringToBytes(Checked, "utf8"))
    End Sub

    Sub ToggleButton6_CheckedChange(Checked As Boolean)
        MQTT.Publish(
    "Relay_6", BC.StringToBytes(Checked, "utf8"))
    End Sub

    Sub ToggleButton7_CheckedChange(Checked As Boolean)
        MQTT.Publish(
    "Relay_7", BC.StringToBytes(Checked, "utf8"))
    End Sub

    Sub BtnStart_Click
        
    'Code to come shortly for auto power off relays...
    End Sub
    Receive message - WeMos D1 mini source code
    Libraries: rESP8266, rESP8266WiFi, rMQTT and rRandomAccessFile

    Code:
    'WIRE LEGEND for 74HC595 shift register
    '8 GND = GND
    '16 Vcc = 5V
    '14 = D1
    '12 = GND
    '12 = D2
    '11 = D3
    '10 = 5V
    'QA to QH is connected to relays 7 to 0

    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'Public variables can be accessed from all modules.

        
    Public Serial1 As Serial

        
    Private AStream As AsyncStreams
        
    Private WiFi As ESP8266WiFi
        
    Private WiFiStr As WiFiSocket
        
    Private MQTT As MqttClient
        
    Private MQTTOpt As MqttConnectOptions
        
    Private MQTTUser As String = "xxxxxxx"
        
    Private MQTTPassword As String = "_xxxxxxx"
        
    Private MQTTHostName As String = "m21.cloudmqtt.com"
        
    Private MQTTPort As Int = 14925
        
    Private DS, STCP, SHCP As Pin
        
    Private Relays As Int = 8
        
    Private Registers(Relays) As Boolean
        
    Private ESPin As D1Pins
    End Sub

    Private Sub AppStart
        Serial1.Initialize(
    115200)
        Delay(
    1000)
        
    Log("AppStart")

        DS.Initialize(ESPin.D1, DS.MODE_OUTPUT) 
    'Arduino Pin 8, SR Pin 14 Serial In
        STCP.Initialize(ESPin.D2, STCP.MODE_OUTPUT) 'Arduino Pin 11, SR Pin 12 RCK
        SHCP.Initialize(ESPin.D3, SHCP.MODE_OUTPUT) 'Arduino Pin 12, SR Pin 11 Serial Clock

        
    'Clear Register Values
        ClearAllReg

        AStream.Initialize(Serial1.Stream, 
    "Astream_NewData""Astream_Error")

        
    'Connect to local WiFi Access Point
        WiFi.Connect2("Access Point""Access Point Password")
        
    If WiFi.IsConnected Then Log("Connected to WiFi, Local IP ", WiFi.LocalIp) Else Log("Not Connected to WiFi")

        
    'Connect to CloudMQTT broker
        Dim ClientId As String = Rnd(0999999999'create a unique id
        MQTT.Initialize2(WiFiStr.stream, MQTTHostName, MQTTPort, ClientId, "MQTT_MessageArrived""MQTT_Disconnected")
        MQTTOpt.Initialize(MQTTUser, MQTTPassword)
        MQTT_Connect(
    0)
    End Sub

    Sub MQTT_MessageArrived (Topic As String, Payload() As Byte)
        
    Log("Topic = ", Topic, " and Payload = ", Payload)

        
    Dim State As Boolean
        
    Dim BC As ByteConverter
        
    If BC.StringFromBytes(Payload) = "true" Then State = True Else State = False

        
    Select Case Topic
            
    Case "Relay_0"
                Registers(
    0) = Not(State)
            
    Case "Relay_1"
                Registers(
    1) = Not(State)
            
    Case "Relay_2"
                Registers(
    2) = Not(State)
            
    Case "Relay_3"
                Registers(
    3) = Not(State)
            
    Case "Relay_4"
                Registers(
    4) = Not(State)
            
    Case "Relay_5"
                Registers(
    5) = Not(State)
            
    Case "Relay_6"
                Registers(
    6) = Not(State)
            
    Case "Relay_7"
                Registers(
    7) = Not(State)
        
    End Select

        WriteToReg
    End Sub

    Sub MQTT_Connect(Unused As Byte)
        
    If MQTT.Connect = False Then
            
    Log("Trying to connect to broker")
            MQTT.Connect2(MQTTOpt)
            CallSubPlus(
    "MQTT_Connect"10000)
        
    Else
            
    Log("Connected to broker")

            
    For i = 0 To Relays - 1
                MQTT.Subscribe(JoinStrings(
    Array As String("Relay_", i)), 0)
            
    Next
        
    End If
    End Sub

    Sub MQTT_Disconnected
        
    Log("Disconnected")
        MQTT.Close
        MQTT_Connect(
    0)
    End Sub

    Sub Astream_NewData (Buffer() As Byte)
        
    Log("Received: ", Buffer)
    End Sub

    Sub AStream_Error
        
    Log("error")
    End Sub

    'Write To Registers
    Private Sub WriteToReg()
        STCP.DigitalWrite(
    False)

        
    Dim i As Int = 0
        
    Do While i <= Relays - 1
            SHCP.DigitalWrite(
    False)
            DS.DigitalWrite(Registers(i))
            SHCP.DigitalWrite(
    True)
            i = i + 
    1
        
    Loop

        STCP.DigitalWrite(
    True)
    End Sub

    'Clear All Registers
    Private Sub ClearAllReg()
        
    Dim i As Int = Relays - 1
        
    Do While i >= 0
            Registers(i) = 
    True 'True = NO
            i = i - 1
            WriteToReg
        
    Loop
    End Sub
    How to wire up the WeMos D1 mini to the shift register, the white wires connects to relays 7 to 0
    Shift-register-WeMos-8-Relays_bb.png

    YouTube video of an Android device controlling 8 relays over 4G


    Enjoy...
     
    Last edited: Jun 26, 2017
    MarkusR, BillMeyer, jmon and 7 others like this.
  2. Erel

    Erel Administrator Staff Member Licensed User

    Great tutorial! For your next project I recommend you to try B4RSerializator. With B4RSerializator it would have been simpler to send the relay number (or name) together with the new state.
     
    Peter Simpson likes this.
  3. hugo ivan

    hugo ivan New Member

    i want to control a nodemcu with an aplicattion
    like power on a led or something like that
     
  4. Peter Simpson

    Peter Simpson Expert Licensed User

    So @Erel, I finally got around to updating both my B4A and B4R code to use B4RSerializator, it works great. I also got rid of all the button click sub events and replaced them all with a single sub linking all the buttons via the same event name, so now I can just use a sender in the one sub. Doing it this way makes for a neater solution, and obviously my code is easier to maintain in just one sub. I have actually integrated this irrigation system into my garden, this includes sprinklers, pumps, hoses the lot, it all works great :)

    Cheers...
     
    Last edited: Mar 16, 2018
    BillMeyer, jmon, Erel and 2 others like this.
  5. Diego La Mattina

    Diego La Mattina New Member

    Dear Peter, you did a wonderful project that I really enjoyed. Here follow you my project a little similar to yours with the management through Google Assistant. Yes, as 4 relays are few I tried to change the project to manage 24 relays via SN74hc595, but I did not succeed.
    By chance would you be so kind as to be able to modify my shetck in order to use it with the shift register as you did?
    Thank you so much .

    ---------------------------------------------------------------

    #include <ESP8266WiFi.h>
    #include "Adafruit_MQTT.h"
    #include "Adafruit_MQTT_Client.h"

    #define Relay1 D1
    #define Relay2 D2
    #define Relay3 D3
    #define Relay4 D4

    #define WLAN_SSID " ---- " // Your SSID
    #define WLAN_PASS " ---- " // Your password

    /************************* Adafruit.io Setup *********************************/

    #define AIO_SERVER "io.adafruit.com" //Adafruit Server
    #define AIO_SERVERPORT 1883
    #define AIO_USERNAME " ---- " // Username
    #define AIO_KEY " ----- " // Auth Key

    //WIFI CLIENT
    WiFiClient client;

    Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

    Adafruit_MQTT_Subscribe Light1 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Relay1"); // Feeds name should be same everywhere
    Adafruit_MQTT_Subscribe Light2 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/Relay2");
    Adafruit_MQTT_Subscribe Light3 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/Relay3");
    Adafruit_MQTT_Subscribe Light4 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/Relay4");

    void MQTT_connect();

    void setup() {
    Serial.begin(115200);

    pinMode(Relay1, OUTPUT);
    pinMode(Relay2, OUTPUT);
    pinMode(Relay3, OUTPUT);
    pinMode(Relay4, OUTPUT);

    // Connect to WiFi access point.
    Serial.println(); Serial.println();
    Serial.print("Connecting to ");
    Serial.println(WLAN_SSID);

    WiFi.begin(WLAN_SSID, WLAN_PASS);
    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }
    Serial.println();

    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    mqtt.subscribe(&Light1);
    mqtt.subscribe(&Light3);
    mqtt.subscribe(&Light2);
    mqtt.subscribe(&Light4);
    }

    void loop() {
    MQTT_connect();


    Adafruit_MQTT_Subscribe *subscription;
    while ((subscription = mqtt.readSubscription(20000))) {
    if (subscription == &Light1) {
    Serial.print(F("Got: "));
    Serial.println((char *)Light1.lastread);
    int Light1_State = atoi((char *)Light1.lastread);
    digitalWrite(Relay1, Light1_State);

    }
    if (subscription == &Light2) {
    Serial.print(F("Got: "));
    Serial.println((char *)Light2.lastread);
    int Light2_State = atoi((char *)Light2.lastread);
    digitalWrite(Relay2, Light2_State);
    }
    if (subscription == &Light3) {
    Serial.print(F("Got: "));
    Serial.println((char *)Light3.lastread);
    int Light3_State = atoi((char *)Light3.lastread);
    digitalWrite(Relay3, Light3_State);
    }
    if (subscription == &Light4) {
    Serial.print(F("Got: "));
    Serial.println((char *)Light4.lastread);
    int Light4_State = atoi((char *)Light4.lastread);
    digitalWrite(Relay4, Light4_State);

    }
    }


    }

    void MQTT_connect() {
    int8_t ret;

    if (mqtt.connected()) {
    return;
    }

    Serial.print("Connecting to MQTT... ");

    uint8_t retries = 3;

    while ((ret = mqtt.connect()) != 0) {
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);
    retries--;
    if (retries == 0) {
    while (1);
    }
    }
    Serial.println("MQTT Connected!");

    }
     
  6. Peter Simpson

    Peter Simpson Expert Licensed User

    Hello @Diego La Mattina, welcome to the community, sorry but I don't use Google assist even though I've been meaning to do so.

    The N74HC595 is an 8-bit shift register, you would need 3 x N74HC595 shift registers to switch 24 relays. The best thing about using shift registers is that you can easily daisy chain multiple shift registers together to switch multiple relays or LEDs for example. For example you can connect 2 N74HC595 shift registers together to switch 16 relays or 3 N74HC595 shift registers to switch 24 relays. To connect one N74HC595 to another N74HC595 you only need positive, ground and two extra wires which connects the output clock pin to the input clock pin and the h-prime pin to the data pin from one N74HC595 to the other N74HC595.

    Basically what I'm saying is that you need 3 * N74HC595 shift registers to do what you need.

    BTW you should be using B4R, you will find it easier, even though the code you posted looks easy enouhg to work with.

    Anyway, I will give you a couple of nice tips, starting with connect 3 * N74HC595 connect then together, there are simple instruction on the net on how to do that.

    In my second block of code above, you just need to change
    Code:
    Private Relays As Int = 8
    to
    Code:
    Private Relays As Int = 24
    then you can add more Select Case Topic, which I would not do.
    Code:
    Case "Relay_7"
        Registers(
    7) = Not(State)
    If you are going to control 24 relays then I would not use Select Case, I would write a small but tidy look to keep the code nice and tidy, it will also keep the sub shorter too.

    If you have not done so already, I highly recommend that you download and install B4R, it's 100% free to use and you will find it a lot easier to get to grips with if you are not proficient at programming in C/C++.

    Give it a free, it's free...
     
  7. Diego La Mattina

    Diego La Mattina New Member

    @Peter Simpson Thanks a lot for answering me. Unfortunately I am a beginner with the programming of C is I thought it was easy to be able to change through the shift register so as to be able to expand the outputs of NodeMcu, but when I see it seems to me a complex thing.
     
  8. Peter Simpson

    Peter Simpson Expert Licensed User

    It's not really complex.
    BTW this forum IS NOT for c development, our community uses a language called B4X which is basically a turbo charged updated version of BASIC which can be used to develop Android or iOS (Apple) apps, desktop or web solutions, Arduino or even Pi solution too, all using information one language called B4X, maybe you should look more into it.

    I have lately learned C++ and C# but I don't used them for anything, only for checking routines found using Google searches, then I convert code to either B4X or VB.Net depending on the application I'm building for clients.

    Back to your issue, if you download B4R in the link at the top of this page and install it as it's 200% free, we on this community will be more than willing to help you get your project up and running. Using shift registers is extremely simple to do, looking at my code above proves that.

    BTW, if you are learning C, how did you manage to find this great forum?
     
    Last edited: Oct 4, 2018
    Diego La Mattina likes this.
  9. Diego La Mattina

    Diego La Mattina New Member

    @Peter Simpson Well dear Peter, I understand I'll try to make the tutorial you've shown modifying as you described to manage the 24 relays. I registered for a free CloudMQTT only 5 users can manage the relays. Now in your tutorial in the sketch I have to enter the access data to the CloudMQTT (email + password for access?). After that how can I view the screen on my smartphone as shown in the video?
     
  10. Peter Simpson

    Peter Simpson Expert Licensed User

    Hello @Diego La Mattina,
    First copy and past my code into B4R and B4A, download the trial version of B4A, then try to replicate by results which should be simple for you to do as it's just copy and paste the code and follow the diagram above. Once you manage to get my example project above working, you should then try to double your relays from 8 to 16.

    I didn't want to create a diagram just for you ;), so here is a diagram taken from the Arduino forum, it's the same thing but instead of connection LED's through resistors, you will be connecting relay packs.

    ShftOut_Schm2.jpg

    ShftOutExmp2_3.gif

    For Android app I developed a bespoke app just for my needs, but you said that you wanted to use Google Assistant. You now have three viable options.
    1. B4A
    2. Android Studio
    3. Eclipse
    I personally always use the very capable B4A for developing my Android app, actually I use B4A to develop all of my Android apps.

    Google assistant integration is not something that I've looked at, but I know that Erel has posted some code on the forum somewhere that uses an intent. You should download the trial version of B4A and then try to make yourself a basic 'Hello World' app with a button press, mine was actually 'Hello Joanne' lol...

    Any, keep posting if you have any more Arduino or ESP questions.
    If you have any B4A questions, then post your questions on the B4A part of this forum.
     
    Diego La Mattina likes this.
  11. Diego La Mattina

    Diego La Mattina New Member

    @Peter Simpson Well well very well you were formidable in the explanation Peter. Yes, I already looked at the wiring diagram as you had sent me, the application I prefer to use the same as yours, I give up Google Assistant. If you kindly had a small guide to create the application like yours I am very grateful to you so I then extend it to the relays I need. Thank you very much for your attention I can not wait to finish this project, I'm passionate about it.
     
  12. Peter Simpson

    Peter Simpson Expert Licensed User

    Hello,

    The code for the demo app I wrote is in the very first post.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice