B4R Question [SOLVED]Strange problem with Wemos Motor Shield and MQTT...

rbghongade

Active Member
Licensed User
Longtime User
Dear friends,
I hooked up the Wemos Motor Shield with a Wemos D1 mini and a DC motor. I can control the motor with inline C code but a strange problem is seen when I try to use MQTT to control the motor.
1) If I try to use the following code the first command is executed properly but the subsequent commands do not work.
B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Dim PWM As Int 'PWM in % Duty Cucle
    Dim indicator As Pin
    Dim d1pins As D1Pins
    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, 1, 100)
    Private const serverPort As UInt = 1883
   
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    indicator.Initialize(d1pins.D4,indicator.MODE_OUTPUT)
    RunNative("stop",Null)
    Delay(500)
    indicator.DigitalWrite(True)
    If wifi.Connect2("****","********") 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_MOTOR", "Mqtt_MessageArrived", "Mqtt_Disconnected")
    Connect(0)
    PWM=100
   
End Sub

Sub Connect(unused As Byte)
    If mqtt.Connect = False Then
        Log("trying to connect again")
        CallSubPlus("Connect", 1000, 0)
        indicator.DigitalWrite(True)
        Return
    End If
    Log("Connected to broker")
    mqtt.Subscribe("FWD", 0)
    mqtt.Subscribe("REV", 0)
    mqtt.Subscribe("BRK", 0)
    indicator.DigitalWrite(False)
       
End Sub
Sub Mqtt_MessageArrived (Topic As String, Payload() As Byte)
    Log("Message arrived. Topic=", Topic, " payload: ", Payload)
    If Topic="FWD" Then
        PWM=bc.stringFromBytes(Payload)
       

        RunNative("drive_cw",Null)
    End If
    If Topic="REV" Then
        PWM=bc.stringFromBytes(Payload)
       

        RunNative("drive_ccw",Null)
    End If
    If Topic="BRK" Then
       
       
        RunNative("sbrake",Null)
    End If
  
End Sub

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



#if C
#include "WEMOS_Motor.h"
//Motor shield I2C Address: 0x30
//PWM frequency: 1000Hz(1kHz)
Motor M1(0x30,_MOTOR_A, 10000);//Motor A
Motor M2(0x30,_MOTOR_B, 10000);//Motor B

void stop (B4R::Object* o){
M1.setmotor(_STOP);
  M2.setmotor( _STOP);
}
void drive_cw (B4R::Object* o) {
    M1.setmotor(_STOP);
  M2.setmotor( _STOP);
   M1.setmotor( _CW, b4r_main::_pwm);
   M2.setmotor(_CW, b4r_main::_pwm);
}
void drive_ccw (B4R::Object* o) {
M1.setmotor(_STOP);
  M2.setmotor( _STOP);
   M1.setmotor( _CCW, b4r_main::_pwm);
   M2.setmotor(_CCW, b4r_main::_pwm);
}
void sbrake (B4R::Object* o) {
   M1.setmotor(_SHORT_BRAKE);
  M2.setmotor( _SHORT_BRAKE);
}
#End if
I modified the code by adding the looper and the solution works but i not an elegant solution as it gives jerky operation of the motor!

B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Dim PWM As Int 'PWM in % Duty Cucle
    Dim indicator As Pin
    Dim d1pins As D1Pins
    Private client As WiFiSocket
    Private wifi As ESP8266WiFi
    Private bc As ByteConverter
    Private mqtt As MqttClient
    Dim command As Int
    Private serverIp() As Byte = Array As Byte(192, 168, 1, 100)
    Private const serverPort As UInt = 1883
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    indicator.Initialize(d1pins.D4,indicator.MODE_OUTPUT)
    RunNative("stop",Null)
    Delay(500)
    indicator.DigitalWrite(True)
    If wifi.Connect2("****","********") 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_MOTOR", "Mqtt_MessageArrived", "Mqtt_Disconnected")
    Connect(0)
    PWM=100
    AddLooper("Looper")
End Sub

Sub Connect(unused As Byte)
    If mqtt.Connect = False Then
        Log("trying to connect again")
        CallSubPlus("Connect", 1000, 0)
        indicator.DigitalWrite(True)
        Return
    End If
    Log("Connected to broker")
    mqtt.Subscribe("FWD", 0)
    mqtt.Subscribe("REV", 0)
    mqtt.Subscribe("BRK", 0)
    indicator.DigitalWrite(False)
       
End Sub
Sub Mqtt_MessageArrived (Topic As String, Payload() As Byte)
    Log("Message arrived. Topic=", Topic, " payload: ", Payload)
    If Topic="FWD" Then
        PWM=bc.stringFromBytes(Payload)
        command=1

    End If
    If Topic="REV" Then
        PWM=bc.stringFromBytes(Payload)
        command=2

    End If
    If Topic="BRK" Then
       
        command=3
    End If
  
End Sub

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

Sub Looper
        Select command
        Case 1
            RunNative("drive_cw",Null)
        Case 2
            RunNative("drive_ccw",Null)
               
        Case 3
            RunNative("sbrake",Null)
           
        End Select
        Delay(100)
   
End Sub

#if C
#include "WEMOS_Motor.h"
//Motor shield I2C Address: 0x30
//PWM frequency: 1000Hz(1kHz)
Motor M1(0x30,_MOTOR_A, 1000);//Motor A
Motor M2(0x30,_MOTOR_B, 1000);//Motor B

void stop (B4R::Object* o){
M1.setmotor(_STOP);
  M2.setmotor( _STOP);
}
void drive_cw (B4R::Object* o) {
    M1.setmotor(_STOP);
  M2.setmotor( _STOP);
   M1.setmotor( _CW, b4r_main::_pwm);
   M2.setmotor(_CW, b4r_main::_pwm);
}
void drive_ccw (B4R::Object* o) {
M1.setmotor(_STOP);
  M2.setmotor( _STOP);
   M1.setmotor( _CCW, b4r_main::_pwm);
   M2.setmotor(_CCW, b4r_main::_pwm);
}
void sbrake (B4R::Object* o) {
   M1.setmotor(_SHORT_BRAKE);
  M2.setmotor( _SHORT_BRAKE);
}
#End if
What may be going wrong with the first code?
The attached arduino library is required to be installed.
 

Attachments

  • WEMOS_Motor_Shield_Arduino_Library.zip
    6.2 KB · Views: 410

rbghongade

Active Member
Licensed User
Longtime User
Dear Erel,
I get the messages proper, it even works for the very first command, but any other subsequent message/command fails to execute, even though received properly.
 
Upvote 0

rbghongade

Active Member
Licensed User
Longtime User
Dear Erel,
Thanks for the prompt reply but still the problem persists.
Will a proper wrapped library for B4R solve the problem?
 
Last edited:
Upvote 0

rbghongade

Active Member
Licensed User
Longtime User
Dear Erel,
This code (without MQTT) works flawlessly:
B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Dim PWM As Int 'PWM in % Duty Cucle
    Dim wemospins As D1Pins
    Dim b1,b2,b3 As Pin
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    b1.Initialize(wemospins.D5,b1.MODE_INPUT_PULLUP)
    b2.Initialize(wemospins.D6,b2.MODE_INPUT_PULLUP)
    b3.Initialize(wemospins.D7,b3.MODE_INPUT_PULLUP)
    Log("AppStart")
    b1.AddListener("b1_StateChanged")
    b2.AddListener("b2_StateChanged")
    b3.AddListener("b3_StateChanged")
    RunNative("stop",Null)
    PWM=100
   
End Sub


Sub b1_StateChanged(State As Boolean)
   
    If State=False Then
        Log("CW")
        RunNative("drive_cw",Null)
    command=1
    End If
End Sub
Sub b2_StateChanged(State As Boolean)
   
    If State=False Then
        Log("CCW")
        RunNative("drive_ccw",Null)
        command=2
    End If
End Sub
Sub b3_StateChanged(State As Boolean)
   
    If State=False Then
        Log("BRAKE")
        RunNative("sbrake",Null)
        command=3
    End If
End Sub


#if C
#include "WEMOS_Motor.h"
//Motor shield I2C Address: 0x30
//PWM frequency: 1000Hz(1kHz)
Motor M1(0x30,_MOTOR_A, 1000);//Motor A
Motor M2(0x30,_MOTOR_B, 1000);//Motor B

void stop (B4R::Object* o){
M1.setmotor(_STOP);
  M2.setmotor( _STOP);
}
void drive_cw (B4R::Object* o) {
   M1.setmotor( _CW, b4r_main::_pwm);
   M2.setmotor(_CW, b4r_main::_pwm);
}
void drive_ccw (B4R::Object* o) {
   M1.setmotor( _CCW, b4r_main::_pwm);
   M2.setmotor(_CCW, b4r_main::_pwm);
}
void sbrake (B4R::Object* o) {
   M1.setmotor(_SHORT_BRAKE);
  M2.setmotor( _SHORT_BRAKE);
}
#End if
 
Upvote 0

rbghongade

Active Member
Licensed User
Longtime User
Dear friends,
I found that the problem mentioned above has got nothing to do with MQTT or WEMOS mini. It is a firmware bug in the STM chip used in the WEMOS Motor Shield!
The I2C communication times out after say 10 seconds. Hence it does not accept the subsequent commands. The work around is to repeat the last command every 5 seconds , which I have done with a timer.
here is the code:
B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Dim PWM As Int 'PWM in % Duty Cucle
    Dim indicator As Pin
    Dim d1pins As D1Pins
    Private client As WiFiSocket
    Private wifi As ESP8266WiFi
    Private bc As ByteConverter
    Private mqtt As MqttClient
    Dim command As Int
    Dim timer1 As Timer
    Private serverIp() As Byte = Array As Byte(192, 168, 1, 100)
    Private const serverPort As UInt = 1883
   
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    indicator.Initialize(d1pins.D4,indicator.MODE_OUTPUT)
    RunNative("stop",Null)
    Delay(500)
    timer1.Initialize("timer1_Tick",5000)
   
    indicator.DigitalWrite(True)
   
    If wifi.Connect2("****","********") 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_MOTOR", "Mqtt_MessageArrived", "Mqtt_Disconnected")
      
   
   
   
    Connect(0)
    PWM=100
    timer1.Enabled=True
   
End Sub

Sub Connect(unused As Byte)
    If mqtt.Connect = False Then
        Log("trying to connect again")
        CallSubPlus("Connect", 1000, 0)
        indicator.DigitalWrite(True)
        Return
    End If
    Log("Connected to broker")
    mqtt.Subscribe("FWD", 0)
    mqtt.Subscribe("REV", 0)
    mqtt.Subscribe("BRK", 0)
    indicator.DigitalWrite(False)
       
End Sub
Sub Mqtt_MessageArrived (Topic As String, Payload() As Byte)
    Log("Message arrived. Topic=", Topic, " payload: ", Payload)
    If Topic="FWD" Then
        PWM=bc.stringFromBytes(Payload)
        command=1

        RunNative("drive_cw",Null)

    End If
    If Topic="REV" Then
        PWM=bc.stringFromBytes(Payload)
        command=2

            RunNative("drive_ccw",Null)

    End If
    If Topic="BRK" Then
       
        command=3

            RunNative("sbrake",Null)

    End If
  
End Sub

Sub Mqtt_Disconnected
    Log("Disconnected")
    mqtt.Close
 
    Connect(0)
 
End Sub
Sub timer1_Tick
    Select command
        Case 1
           
               
            RunNative("drive_cw",Null)
        Case 2
           
            RunNative("drive_ccw",Null)
               
        Case 3
               
            RunNative("sbrake",Null)
           
    End Select
End Sub


#if C
#include <WEMOS_Motor.h>
//Motor shield I2C Address: 0x30
//PWM frequency: 1000Hz(1kHz)
Motor M1(0x30,_MOTOR_A, 10000);//Motor A
Motor M2(0x30,_MOTOR_B, 10000);//Motor B

void stop (B4R::Object* o){
M1.setmotor(_STOP);
  M2.setmotor( _STOP);
}
void drive_cw (B4R::Object* o) {
    M1.setmotor(_STOP);
  M2.setmotor( _STOP);
   M1.setmotor( _CW, b4r_main::_pwm);
   M2.setmotor(_CW, b4r_main::_pwm);
}
void drive_ccw (B4R::Object* o) {
M1.setmotor(_STOP);
  M2.setmotor( _STOP);
   M1.setmotor( _CCW, b4r_main::_pwm);
   M2.setmotor(_CCW, b4r_main::_pwm);
}
void sbrake (B4R::Object* o) {
   M1.setmotor(_SHORT_BRAKE);
  M2.setmotor( _SHORT_BRAKE);
}
#End if

Apologies to Erel for wasting his time!
 
Upvote 0
Top