B4R Question Controlling WS2812 RGB Stripes with ESP32 and B4A

h725

Active Member
Licensed User
Longtime User
Hello Community,
I am a little bit stuck on the following task:

I would like to access an ESP32 through WLAN (no internet availible) with a B4A application
which controls WS2812 RGB stripes. I have searched the forum, but I did not get a solution yet.

Concerning the WS2812 stripes, I found a suitable libary:

Concerning the ESP32 in combination with B4A I found a sample project which uses MQTT:

First of all I would like to know if mqtt is the correct direction. I am a little bit confused on the following
sentence, quoted from the last link:
"The B4A project is attached. I'm running an external MQTT broker. You can run it in your B4A project if you like."

What does "External MQTT broker" mean in this case? I would like to make an offline project, working with
B4A (for mobile Android device) and B4R for ESP32 board. Internet is not availible. It will use a standalone
Accesspoint due to range optimization.

Maybe I am on the wrong way and somebody has another solution.


Kind regards
h725
 

hatzisn

Expert
Licensed User
Longtime User
External MQTT broker means a broker which is located in the cloud (outside your local network). If you use MQTT inside a WiFi then you will have to create a B4J application with an MQTT Broker (moquette) accessible through wifi (no internet needed).

For the NeoPixel strip googling it I found this:

The approximate peak power use (all LEDs on at maximum brightness) per meter is: 30 LEDs: 9 Watts (about 1.8 Amps at 5 Volts). 60 LEDs: 18 Watts (about 3.6 Amps at 5 Volts). 144 LEDs : 43 watts (8.6 Amps at 5 Volts).

This means you will definitely need an external power provision since all ESPs are 3.3V providing max 12mA from GPIO pins. I've never had a neopixel strip so I do not know how you can handle the signals for the colors but my sense is that you will need to use some MOSFETs with external power provision (I suppose there will be some analogWrites).
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
I found this also:

Does ESP32 have analogWrite?

Simple. The ESP32 does not support the analogWrite() function. But it does support a much better one, the ledcWrite() function. The ledcWrite() is very similar to analogWrite().

You can use it in B4R with InLine C.
 
Last edited:
Upvote 0

h725

Active Member
Licensed User
Longtime User
Thank you for the information.
I have already checked the neopixel library in standalone mode on an esp32 and it is working fine.

Is it possible to use MQTT Broker parallel to the MQTT Client in a B4A app?
Maybe somebody has another - more easier - solution.

Kind regards
h725
 
Upvote 0

XorAndOr

Active Member
Licensed User
Longtime User
I have already checked the neopixel library in standalone mode on an esp32 and it is working fine.
So you need the connection with esp and b4a. You could create on esp 32 an access poin with ssid and password that remains listening.
When you open the app you connect with esp and command the leds.
Of course, the distance range is limited.
I have not tried with Esp32, you can find many examples of access points on esp8266 on the forum.
Maybe it works the same on esp32.
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
I have already checked the neopixel library in standalone mode on an esp32 and it is working fine.

If I were you I would double check the current it draws and the voltages. It is possible that it will burn a pin. If it communicates through RX, TX then it can burn a pin if there is a voltage regulator inside it for 5 Volts.

Is it possible to use MQTT Broker parallel to the MQTT Client in a B4A app?
Maybe somebody has another - more easier - solution.

I have heard that before and I think (I am definitely not sure) if you place the broker libary also in the B4A additional libraries directory it will work (I may confuse it with another library).
 
Upvote 0

h725

Active Member
Licensed User
Longtime User
"So you need the connection with esp and b4a. You could create on esp 32 an access poin with ssid and password that remains listening." - I am not sure what makes more sense. Using the ESP32 as an AP (maybe with modified antenna) or an external accesspoint which will definitely enhance the range.

"If I were you I would double check the current it draws and the voltages. It is possible that it will burn a pin. If it communicates through RX, TX then it can burn a pin if there is a voltage regulator inside it for 5 Volts." - Maybe I am on the wrong way - I am already working with the neopixel library and WS2812 stripes and the ordinary Arduino IDE and this is working fine (I use an external 5V source.) Is there any difference?

I just made a small modification on the mentioned project (esp 8266 + relay):

Modified relay example:
Sub Process_Globals
    Private client As MqttClient
    Public connected As Boolean
    Dim broker As MqttBroker
End Sub

Sub Service_Create
   
    broker.Initialize("", 51042) 'first parameter is the event name. It is currently not used.
    broker.DebugLog = True
    broker.Start
 
    client.Initialize("client", "tcp://192.168.178.30:51042", "android")
    client.Connect
End Sub

And it is working - standalone with ESP32 and an android device!!
 
Upvote 0

h725

Active Member
Licensed User
Longtime User
I have got another question concerning this task:

Is it possible to access several ESP32 boards parallel from my B4A application?
I would like to use several ESP32 boards through WLAN which I access from my B4A application.
They all have the same WS2812 stripes connected, so I would like to push one button on my B4A
App and all boards react. I tried it without any changement in code but only one device is responding.
 
Upvote 0

rbghongade

Active Member
Licensed User
Longtime User
Hi,
Here is my project (probably 4 years old) using ESP8266. With some modifications you may be able to adapt it to your use.
B4R:
Sub Process_Globals
    Public Serial1 As Serial
    Dim R,G,B,ledno,RED,BLUE,GREEN As Int
    Dim indicator As Pin
    Dim d1pins As Wemos_D1_R2_Pins
    Private client As WiFiSocket
    Private wifi As ESP8266WiFi
    Private bc As ByteConverter
    Private mqtt As MqttClient
    Private serverIp() As Byte = Array As Byte(192, 168, 43, 1)
    Private const serverPort As UInt = 51042
    Dim TIMER1 As Timer
    Dim TIMER2 As Timer
    Dim I As Int
   
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    indicator.Initialize(d1pins.D4,indicator.MODE_OUTPUT)
    TIMER1.Initialize("TIMER1_Tick",15000)
    TIMER2.Initialize("TIMER2_Tick",30000)
    TIMER1.Enabled=True
    Log("AppStart")
    indicator.DigitalWrite(True)
    RunNative("setup",Null)
    If wifi.Connect2("ATSYS","******") Then
        client.ConnectIP(serverIp,serverPort)
        Log("Waiting for connection.")
        Log("My ip: ", wifi.LocalIp)
    Else
        Log("Failed to connect to Wifi.")
    End If
    mqtt.Initialize(client.Stream, serverIp, serverPort, "ESP", "Mqtt_MessageArrived", "Mqtt_Disconnected")
     
   
   
 
   
 
    Connect(0)
End Sub
Sub Connect(unused As Byte)
    If mqtt.Connect = False Then
        Log("trying to connect again")
        CallSubPlus("Connect", 1000, 0)
        indicator.DigitalWrite(True)
        TIMER1.Enabled=True
        Return
    End If
    Log("Connected to broker")
    mqtt.Subscribe("COLOR", 0)
    indicator.DigitalWrite(False)
   
   
   
   
End Sub
Sub Mqtt_MessageArrived (Topic As String, Payload() As Byte)
    Log("Message arrived. Topic=", Topic, " payload: ", Payload)
    If Topic="COLOR" Then
        RED=bc.StringFromBytes(bc.SubString2(Payload,0,3))
       
        GREEN=bc.StringFromBytes(bc.SubString2(Payload,3,6))
        BLUE=bc.StringFromBytes(bc.SubString2(Payload,6,9))
        Log(RED)
        Log(GREEN)
        Log(BLUE)
        For j=0 To 63
            led_data(j,RED,GREEN,BLUE)
        Next
       
    End If
    TIMER1.Enabled=False
    TIMER2.Enabled=True
End Sub

Sub Mqtt_Disconnected
    Log("Disconnected")
    mqtt.Close
 
    Connect(0)
 
End Sub


Sub led_data(n As Int,r1 As Int,g1 As Int, b1 As Int)
    R=r1
    G=g1
    B=b1
    ledno=n
    RunNative("show",Null)
End Sub

Sub TIMER1_Tick
    Log("OK")
    I=Rnd(0,9)
    Select I
        Case 0
            RED=255
            GREEN=0
            BLUE=0
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 1
            RED=0
            GREEN=255
            BLUE=0
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 2
            RED=0
            GREEN=0
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 3
            RED=255
            GREEN=255
            BLUE=0
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 4
            RED=255
            GREEN=0
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 5
            RED=255
            GREEN=0
            BLUE=0
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 6
            RED=0
            GREEN=255
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 7
            RED=142
            GREEN=0
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 8
            RED=123
            GREEN=255
            BLUE=123
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 9
            RED=255
            GREEN=255
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
    End Select

End Sub
Sub TIMER2_Tick
    TIMER1.Enabled=True
    TIMER2.Enabled=False
End Sub
#if C
#include <Adafruit_NeoPixel.h>

#define PIN D6
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(64, PIN, NEO_GRB + NEO_KHZ800);
void setup(B4R::Object* o){
wifi_station_set_auto_connect(true);
pixels.setBrightness(35);
  pixels.begin();
 }
   
void show(B4R::Object* o) {
pixels.setPixelColor(b4r_main::_ledno,pixels.Color(b4r_main::_r, b4r_main::_g,b4r_main::_b));
  // pixels.setPixelColor(0, pixels.Color(255,0,0));
     pixels.show();
}

#End if
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
Hi,
Here is my project (probably 4 years old) using ESP8266. With some modifications you may be able to adapt it to your use.
B4R:
Sub Process_Globals
    Public Serial1 As Serial
    Dim R,G,B,ledno,RED,BLUE,GREEN As Int
    Dim indicator As Pin
    Dim d1pins As Wemos_D1_R2_Pins
    Private client As WiFiSocket
    Private wifi As ESP8266WiFi
    Private bc As ByteConverter
    Private mqtt As MqttClient
    Private serverIp() As Byte = Array As Byte(192, 168, 43, 1)
    Private const serverPort As UInt = 51042
    Dim TIMER1 As Timer
    Dim TIMER2 As Timer
    Dim I As Int
 
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    indicator.Initialize(d1pins.D4,indicator.MODE_OUTPUT)
    TIMER1.Initialize("TIMER1_Tick",15000)
    TIMER2.Initialize("TIMER2_Tick",30000)
    TIMER1.Enabled=True
    Log("AppStart")
    indicator.DigitalWrite(True)
    RunNative("setup",Null)
    If wifi.Connect2("ATSYS","******") Then
        client.ConnectIP(serverIp,serverPort)
        Log("Waiting for connection.")
        Log("My ip: ", wifi.LocalIp)
    Else
        Log("Failed to connect to Wifi.")
    End If
    mqtt.Initialize(client.Stream, serverIp, serverPort, "ESP", "Mqtt_MessageArrived", "Mqtt_Disconnected")
 
 
 
 
 
 
    Connect(0)
End Sub
Sub Connect(unused As Byte)
    If mqtt.Connect = False Then
        Log("trying to connect again")
        CallSubPlus("Connect", 1000, 0)
        indicator.DigitalWrite(True)
        TIMER1.Enabled=True
        Return
    End If
    Log("Connected to broker")
    mqtt.Subscribe("COLOR", 0)
    indicator.DigitalWrite(False)
 
 
 
 
End Sub
Sub Mqtt_MessageArrived (Topic As String, Payload() As Byte)
    Log("Message arrived. Topic=", Topic, " payload: ", Payload)
    If Topic="COLOR" Then
        RED=bc.StringFromBytes(bc.SubString2(Payload,0,3))
 
        GREEN=bc.StringFromBytes(bc.SubString2(Payload,3,6))
        BLUE=bc.StringFromBytes(bc.SubString2(Payload,6,9))
        Log(RED)
        Log(GREEN)
        Log(BLUE)
        For j=0 To 63
            led_data(j,RED,GREEN,BLUE)
        Next
 
    End If
    TIMER1.Enabled=False
    TIMER2.Enabled=True
End Sub

Sub Mqtt_Disconnected
    Log("Disconnected")
    mqtt.Close
 
    Connect(0)
 
End Sub


Sub led_data(n As Int,r1 As Int,g1 As Int, b1 As Int)
    R=r1
    G=g1
    B=b1
    ledno=n
    RunNative("show",Null)
End Sub

Sub TIMER1_Tick
    Log("OK")
    I=Rnd(0,9)
    Select I
        Case 0
            RED=255
            GREEN=0
            BLUE=0
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 1
            RED=0
            GREEN=255
            BLUE=0
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 2
            RED=0
            GREEN=0
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 3
            RED=255
            GREEN=255
            BLUE=0
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 4
            RED=255
            GREEN=0
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 5
            RED=255
            GREEN=0
            BLUE=0
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 6
            RED=0
            GREEN=255
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 7
            RED=142
            GREEN=0
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 8
            RED=123
            GREEN=255
            BLUE=123
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
        Case 9
            RED=255
            GREEN=255
            BLUE=255
            For j=0 To 63
                led_data(j,RED,GREEN,BLUE)
            Next
    End Select

End Sub
Sub TIMER2_Tick
    TIMER1.Enabled=True
    TIMER2.Enabled=False
End Sub
#if C
#include <Adafruit_NeoPixel.h>

#define PIN D6
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(64, PIN, NEO_GRB + NEO_KHZ800);
void setup(B4R::Object* o){
wifi_station_set_auto_connect(true);
pixels.setBrightness(35);
  pixels.begin();
 }
 
void show(B4R::Object* o) {
pixels.setPixelColor(b4r_main::_ledno,pixels.Color(b4r_main::_r, b4r_main::_g,b4r_main::_b));
  // pixels.setPixelColor(0, pixels.Color(255,0,0));
     pixels.show();
}

#End if

Hi, the object Wemos_D1_R2_Pins in which library is it? I substituted it with the D1Pins from the library rESP8266.
 
Last edited:
Upvote 0

h725

Active Member
Licensed User
Longtime User
I would like to share the current development status:

I faced with the problem that only one device was responding. The solution was quite simple.
I forgot to assign a unique id for the device. So in B4R the code is:


B4X:
    mqtt.Initialize(client.Stream, Array As Byte(192, 168, 178, 30), _
     51042, "uniquieClientID", "Mqtt_MessageArrived", "Mqtt_Disconnected")

You have to change the clientID "uniquieClientID" for every device. That means:

Device 1:

B4X:
    mqtt.Initialize(client.Stream, Array As Byte(192, 168, 178, 30), _
     51042, "esp1", "Mqtt_MessageArrived", "Mqtt_Disconnected")

Device2:

B4X:
    mqtt.Initialize(client.Stream, Array As Byte(192, 168, 178, 30), _
     51042, "esp2", "Mqtt_MessageArrived", "Mqtt_Disconnected")

Device3:

B4X:
    mqtt.Initialize(client.Stream, Array As Byte(192, 168, 178, 30), _
     51042, "esp3", "Mqtt_MessageArrived", "Mqtt_Disconnected")

etc.
 
Last edited:
Upvote 0
Hi,
Thanks to all for sharing their helpful thoughts. Just a question raised in mind that how many MQTT clients can be handle with one B4A/B4J MQTT Broker? Is there some delay in communication if a reasonable quantity of clients publish/subscribe at the same time? Thanks.
 
Upvote 0
Top