B4R Question NODEMCU send problems

cas6678

Active Member
Licensed User
Longtime User
I have a nodemcu that detects the change of state of a pin.

I have based my code in the code example @Filippo.

https://www.b4x.com/android/forum/t...on-problems-with-udpsocket.72239/#post-460935

In my code when the change of state of one pin is detected, a counter is incremented and is sent via wifi.

I've done various tests and always have error. I did not notice some changes state.

This happens to me with different pins.

But if not sent, and I do just at the end of the test, the reading is correct. All state changes are detected.

This leads me to think that the problem is sending. But I made a log of how long it takes to send and this occurs in micros 150/200, is fast.

My code:

B4X:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 600
#End Region

Sub Process_Globals
    Public Serial1 As Serial
    Public WiFi As ESP8266WiFi
    Private bc As ByteConverter
    Dim MacArray(6) As Byte
    Private server(2) As WiFiServerSocket
    Private astream(2) As AsyncStreams
    Private pinSensor As Pin
    Private pin1 As D1Pins
    Private contador As Long
    Private codigo As Int
End Sub

Private Sub AppStart
    Log("AppStart")
    Serial1.Initialize(115200)
    Dim Passwd As String = bc.HexFromBytes(bc.SubString2(MacAddress, 0, 4))
    Log("StartAP: ", WiFi.StartAccessPoint2("fgWifi", Passwd))
    Log("My AP ip: ", WiFi.AccessPointIp)
    Log(Passwd)
    IntiServer
End Sub

#Region "server-Subs"
Public Sub IntiServer  
    server(0).Initialize(51041, "Server1_NewConnection")
    server(0).Listen
    server(1).Initialize(51042, "Server2_NewConnection")
    server(1).Listen
    pinSensor.Initialize(pin1.D1, pinSensor.MODE_INPUT_PULLUP)
    pinSensor.AddListener("pinSensor_StateChanged")
End Sub

Sub Server1_NewConnection (NewSocket As WiFiSocket)
    Log("Server1_NewConnection=" , NewSocket.Connected)
    If server(0).Socket.Connected Then
        astream(0).Initialize(NewSocket.Stream, "astream_NewData", "astream1_Error")
        astream(0).Write(bc.StringToBytes("OK"))
    End If
End Sub

Sub Server2_NewConnection (NewSocket As WiFiSocket)
    Log("Server2_NewConnection=" , NewSocket.Connected)
    If server(1).Socket.Connected Then
        astream(1).Initialize(NewSocket.Stream, "astream_NewData", "astream2_Error")
        astream(1).Write(bc.StringToBytes("OK"))
    End If
End Sub

Sub astream_NewData (Buffer() As Byte)
    Dim cod As String = bc.StringFromBytes(Buffer)
    codigo=cod
    SendValue
End Sub

Sub astream1_Error
    Log("astream1_Error")
    If Not(server(0).Socket.Connected) Then
        Log("server(0).Listen=", 0)
        server(0).Listen
    End If
End Sub

Sub astream2_Error
    Log("astream2_Error")
    If Not(server(1).Socket.Connected) Then
        Log("server(1).Listen=", 1)
        server(1).Listen
    End If
End Sub
#End Region

Sub pinSensor_StateChanged (State As Boolean)
    If State Then
            contador=contador+1
            SendValue
        End If  
End Sub

Sub SendValue
        Dim key As String
        key=NumberFormat(contador*100+codigo,0,0)
        If server(0).Socket.Connected Then
            astream(0).Write(key).Write(",")
        End If
        If server(1).Socket.Connected Then
            astream(1).Write(key).Write(",")
        End If
End Sub

Sub MacAddress() As Byte()
    RunNative("getMac", Null)
    Return MacArray
End Sub

#if C
  #include <ESP8266WiFi.h>
  void getMac(B4R::Object* u) {
  WiFi.macAddress((Byte*)b4r_main::_macarray->data);
  }
#end if
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. Why do you need two sockets? Check this network example: https://www.b4x.com/android/forum/threads/how-to-setup-wemos-d1-r2-as-server.69654/#content

2. As a general rule you should avoid sending strings and prefer sending binary values. You can use the new B4RSerializator tool for this: https://www.b4x.com/android/forum/threads/72404/#content

3. Try this:
B4X:
Sub pinSensor_StateChanged (State As Boolean)
If State Then
 contador=contador+1
 CallSubPlus("SendValue", 10, 0)
End If
End Sub


Sub SendValue(u As Byte)
 ...
End Sub
 
Upvote 0

cas6678

Active Member
Licensed User
Longtime User
Why two? I need the nodemcu can communicate with two different devices.
Surely there will be better ways to do it but with my knowledge I find it difficult to apply.
I saw the example proposed by me and I find that a connection external is needed in this example. This is correct? I want the nodem and devices are autonomous.

2. As a general rule you should avoid sending strings and prefer sending binary values. You can use the new B4RSerializator tool for this: https://www.b4x.com/android/forum/threads/72404/#content

3. Try this:
B4X:
Sub pinSensor_StateChanged (State As Boolean)
If State Then
contador=contador+1
CallSubPlus("SendValue", 10, 0)
End If
End Sub


Sub SendValue(u As Byte)
...
End Sub

I made the proposed changes.

1 sockets,
callsubplus, and
B4RSerializator tool.

But the results are the same.

I've even removed the pin input_pullup and I put a physical resistance (pull-down) but still the same.

I tried not connected the android to nodemcu. I move the wheel at different speeds and then connect to read and the result is correct in this way.

Any inconsistency exists between astream.write and pinsensorchanged that I can not understand. pinsensorchanged only fails if astream.write is running

My code now:

B4X:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 600
#End Region

Sub Process_Globals
    Public Serial1 As Serial
    Private server As WiFiServerSocket
    Private pinSensor1 As Pin
    Private pin1 As D1Pins
    Private wifi As ESP8266WiFi
    Private astream As AsyncStreams
    Private ser As B4RSerializator
    Private contador As Long
    Private codigo As Int
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    Log("StartAP: ", wifi.StartAccessPoint2("CAS", 12345678))
    Log("My AP ip: ", wifi.AccessPointIp)
    server.Initialize(51042, "Server_NewConnection")
    server.Listen
    pinSensor1.Initialize(pin1.D1, pinSensor1.MODE_INPUT)
    pinSensor1.AddListener("pinSensor1_StateChanged")
    codigo=50
End Sub

Sub Server_NewConnection (NewSocket As WiFiSocket)
    Log("new connection")
    astream.Initialize(NewSocket.Stream, "astream_NewData", "astream_Error")
End Sub

Sub astream_NewData (Buffer() As Byte)
    Dim be(10) As Object 'used as a storage buffer.
    Dim objects() As Object = ser.ConvertBytesToArray(Buffer, be)
    Log("Recieved:")
    For Each o As Object In objects
        Log(o)
    Next
End Sub

Sub Astream_Error
    Log("Error.")
    server.Listen
End Sub

Sub pinSensor1_StateChanged (State As Boolean)
    If State Then
       contador=contador+1
       CallSubPlus("SendValue",10,0)
    End If 
End Sub

Sub SendValue (u As Byte)
    If server.Socket.Connected Then
        astream.Write(ser.ConvertArrayToBytes(Array(contador,",",codigo,",")))
    End If
End Sub
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I've tested your code here and it works properly here.

I've used this code:
B4X:
#Region Project Attributes
  #AutoFlushLogs: True
  #CheckArrayBounds: True
  #StackBufferSize: 600
#End Region

Sub Process_Globals
  Public Serial1 As Serial
  Private server As WiFiServerSocket
  Private pinSensor1 As Pin
  Private pin1 As D1Pins
  Private wifi As ESP8266WiFi
  Private astream As AsyncStreams
  Private ser As B4RSerializator
  Private contador As Long
  Private codigo As Int
End Sub

Private Sub AppStart
  Serial1.Initialize(115200)
  Log("AppStart")
   Log(wifi.Connect("dlink"))
   Log(wifi.LocalIp)
  server.Initialize(51042, "Server_NewConnection")
  server.Listen
  pinSensor1.Initialize(pin1.D3, pinSensor1.MODE_INPUT_PULLUP)
  pinSensor1.AddListener("pinSensor1_StateChanged")
  codigo=50
End Sub

Sub Server_NewConnection (NewSocket As WiFiSocket)
  Log("new connection")
  astream.Initialize(NewSocket.Stream, "astream_NewData", "astream_Error")
End Sub

Sub astream_NewData (Buffer() As Byte)
  Dim be(10) As Object 'used as a storage buffer.
  Dim objects() As Object = ser.ConvertBytesToArray(Buffer, be)
  Log("Recieved:")
  For Each o As Object In objects
  Log(o)
  Next
End Sub

Sub Astream_Error
  Log("Error.")
  server.Listen
End Sub

Sub pinSensor1_StateChanged (State As Boolean)
  If State Then
  contador=contador+1
    Log("Value: ", contador)
  CallSubPlus("SendValue",10,0)
  End If
End Sub

Sub SendValue (u As Byte)
  If server.Socket.Connected Then
  astream.Write(ser.ConvertArrayToBytes(Array(contador,",",codigo,",")))
  End If
End Sub

With the attached B4J program.

Tested on WeMos D1.

B4J logs:
connected: true
*************
1
,
50
,
*************
2
,
50
,
*************
3
,
50
,
*************
4
,
50
,
*************
5
,
50
,
 

Attachments

  • B4J.zip
    3.5 KB · Views: 251
Upvote 0

cas6678

Active Member
Licensed User
Longtime User
Yes. On my desk also it works well.

I only find two possible differences with your test.

I have a nodemcu not a WEMOS
Speed: I do not know how fast your log has been tested. My project cycle status change LOW-HIGH-LOW occurs in 25 millis and duration of the state can become HIGH only 350 micros. I thought this should not be a problem because I work in a arduino nano with a simple code without problems.

I will test arduino nano but with B4R code to analyze better.

Thanks.
 
Upvote 0

cas6678

Active Member
Licensed User
Longtime User
This could be the problem. You might need to add a buffer. Store 10 messages and then send all of them.
I think not. Look. I do this and still have error.

B4X:
Sub pinSensor1_StateChanged (State As Boolean)
    If State Then
        contador=contador+1
    Else
        CallSubPlus("SendValue",10,0)
    End If   
End Sub

Sub SendValue (u As Byte)
    If server.Socket.Connected Then
        If Millis > time2 + 1000 Then
            astream.Write(ser.ConvertArrayToBytes(Array(contador,",",codigo,",")))
            time2=Millis
        End If   
    End If
End Sub

Sending each second, the error is the same.

The problem is not too many send. The problem is the coincidence in time the send with status change pin. If send occurs, pin change is not detected. I did different code, timer, loopers, and the error occurs just to send. Whitout send, the measure is perfect always, at least to the maximum speed that my car can reach ;)

I think is hardware problem, maybe i don't know something about nodemcu configuration. I buy Wemos, it arrive in a few days and test whit it and report result.

Thanks for your help @Erel and thanks for b4x, it's great.
 
Upvote 0

cas6678

Active Member
Licensed User
Longtime User
Flushing the network buffer on ESP8266 takes about 100 - 200 milliseconds. It will happen after SendValue completes. Nothing will be detected during this period.
Your post clearly explains my problem.

Then the same thing happen with Wemos

This happens only when sending? and receiving?

Maybe my solution will have a arduino counting and pass the value to nodemcu to send.
 
Upvote 0
Top