B4R Question Serial text without carriage return is not recognized.

Tim Chapman

Active Member
Licensed User
Longtime User
I added an EMIC 2 speech synthesizer to my robot project.
It works beautifully.
When it finishes speaking, it sends a colon ":" our of its serial port.
That serial data is received on the Hardware Serial Port 2 of my Arduino Mega 2560.
Since it has no carriage return, the data is not seen by the Arduino.
Is there any way to fix this?

Line 55 of my code below is not sending anything. But it works correctly in other instances.

This is the relevant code:

My B4R Code:
Sub Process_Globals
    'TXD2/RXD2 Serial for EMIC 2 Text to Speech Synthesizer.  See:  D:\Electronics\Data Sheets\Emic 2 Text to Speech Module
    Private SerialNative2 As Stream 'https://www.b4x.com/android/forum/threads/additional-hardware-serial-ports.67150/
    Private Emic2Stream As AsyncStreams
End Sub

Private Sub AppStart
    'Serial for EMIC 2 Text to Speech Synthesizer connected to Hardware Serial Port 1.
    RunNative("SerialNative2", Null)
    Emic2Stream.Initialize(SerialNative2, "Emic2Stream_NewData", Null)
   
        Delay(2000)
   
    CommandEMIC2("H","")
    Delay(5000)
   
    For VoiceNumber = 0 To 8

    CommandEMIC2("N",VoiceNumber)
        Delay(1000)

        CommandEMIC2("V", 18)
       
        Delay(1000)
        Speak("Hello! My name is Emic 2. Nice to meet you.")
        Delay(5000)
    Next
End Sub

Private Sub Speak(SendData As String)
    Private eol2() As Byte = Array As Byte(13)
        Dim SendData As String = JoinStrings(Array As String("S", SendData))
        'Log("Send Data = ", SendData)

        'Send data to EMIC 2 connected to Hardware Serial Port 2.
        Dim Buffer() As Byte = SendData
        Emic2Stream.Write(Buffer)
        Emic2Stream.Write(eol2) 'end of line character. AsyncStreamsText will cut the message here
End Sub

Private Sub CommandEMIC2(SendData1 As String, SendData2 As String)
    Private eol2() As Byte = Array As Byte(13)
        Dim SendData As String = JoinStrings(Array As String(SendData1, SendData2))
        Log("Command Data = ", SendData)

        'Send data to EMIC 2 connected to Hardware Serial Port 2.
        Dim Buffer() As Byte = SendData
        Emic2Stream.Write(Buffer)
        Emic2Stream.Write(eol2) 'end of line character. AsyncStreamsText will cut the message here
End Sub

Private Sub Emic2Stream_NewData (Buffer() As Byte) 'Data from EMIC 2 Text to Speech Synthesizer
    Log("Buffer = ", Buffer)
    Private eol2() As Byte = Array As Byte(13)
    PCStream.Write(Buffer) 'Send data out via Bluetooth connection to bluetooth receiver on the PC.
    PCStream.Write(eol2) 'end of line character. AsyncStreamsText will cut the message here
End Sub
 

emexes

Expert
Licensed User
Since it has no carriage return, the data is not seen by the Arduino.
Why do you say that?

Emic2Stream_NewData should be delivering the colon, regardless of whether it has a carriage return after it or not.

What is Log("Buffer = ", Buffer) showing?

Tbh I'm surprised it's showing anything, but maybe things are different in B4R.

The following works in B4J, if that's of any use:
B4X:
Dim sb As StringBuilder
sb.Initialize

Dim Separator As String = ""
For Each B As Byte In Buffer
    sb.Append(Separator & B)
    Separator = ", "
Next

Log("Buffer = " & sb.ToString)
 
Upvote 0

emexes

Expert
Licensed User
That serial data is received on the Hardware Serial Port 2 of my Arduino Mega 2560.
Since it has no carriage return, the data is not seen by the Arduino.
Maybe I've misunderstood. The colon is received but not seen? Or are there two separate Arduinos? (I thought the system had just the one Arduino)
 
Upvote 0

emexes

Expert
Licensed User
It is sent
From the Emic2 to the Arduino?

and not seen.
Is it the same two-way channel that commands TO the Emic2 are sent over? as in, if the other direction is working, then the serial format and bit rate are probably correct.

Has *anything* been received from the Emic2 over that serial link? Like, does it receive other stuff, but not the colon? Or is it completely dark, in which case: maybe there's a hardware issue eg cracked track, bad joint, broken wire.


I know it is sent because the datasheet says it is
Thank you for injecting some humour into the situation.
 
Upvote 0

Tim Chapman

Active Member
Licensed User
Longtime User
Yes. From the Emic2 to the Arduino.
I have not seen anything from the EMIC2.
Every command sends a colon in response.
The H command is supposed to send a list of available commands which sends nothing. So, maybe you are right about a hardware failure. I will check that further.
I am working on a different programming project for my business tonight so the robot is on the back burner.
 
Upvote 0

Tim Chapman

Active Member
Licensed User
Longtime User
I finally found the problem. Everything works now. I found (again after forgetting) that a Delay statement causes the serial input to be missed. My bad.
 
Upvote 0

Tim Chapman

Active Member
Licensed User
Longtime User
Since serial communication is interrupt driven and they are blocked by delays, I figure that all interrupt driven events would be blocked. Any will have to be tested to know for sure.
 
Upvote 0

emexes

Expert
Licensed User
Attached is my code so far.



Warmed my heart to see a MPU6050 in there.

Some timeout code did look a tad more complicated than it needs to be. Assuming that the 32-bit math functions wrap-around without complaining, and that time doesn't go backwards (except at 32-bit rollover), then I am reasonably certain that this:

B4X:
If Millis > 4294965295 Then 'Within 2000 of overflowing. 4294967295 - 2000
    RobotStopTimerStart = 2000 - (4294967295 - Millis) 'Calculate what the RobotStopTimer should be to give one second for it to stop while taking into account the overflow of Millis.
Else
    RobotStopTimerStart = Millis
End If
                
Do Until Millis > RobotStopTimerStart + 2000 'Allow 1 second for the robot to stop
Loop

could be reduced to this:

B4X:
RobotStopTimerStart = Millis

Do Until Millis - RobotStopTimerStart > 2000    'Allow 1 second for the robot to stop
Loop
 
Upvote 0

Tim Chapman

Active Member
Licensed User
Longtime User
It overflows at 4294967295 millis.
If:
RobotStopTimerStart = 4294966295 (1000 less than rollover)
Millis = 500 (any value will work here).

Millis - RobotStopTimerStart = -4294965795

It seems to me that it will be a long time until it reaches 2000.
Am I missing something here?
 
Upvote 0

emexes

Expert
Licensed User
Am I missing something here?
Yes.

Millis is about to wraparound from 0xFFFFFFFF to 0x00000000.

And that similar wraparound should occur with 32-bit (B4R Long or ULong) math.

The result you get in B4R is not the same as the result you would get on a pocket calculator.

B4X:
Dim RobotStopTimerStart As ULong = 4294966295    '(1000 less than rollover)
Dim MyMillis As ULong = 500    '(any value will work here).
Dim Elapsed As ULong = MyMillis - RobotStopTimerStart

Log(Elapsed)
 
Upvote 0

emexes

Expert
Licensed User
It is interesting with 32-bit arithmetic ie modulo 2^32, that:
B4X:
Do Until Millis > RobotStopTimerStart + 2000    'Allow 1 second for the robot to stop
and
B4X:
Do Until Millis - RobotStopTimerStart > 2000    'Allow 1 second for the robot to stop
are not equivalent. 🫣

The latter fights fire with fire, turning the wraparound problem back onto itself.
 
Last edited:
Upvote 0

Tim Chapman

Active Member
Licensed User
Longtime User
How do we know that the math being done in the Do Until Millis > RobotStopTimerStart + 2000 statement is using the right kind of variable that will wrap properly? Since the sum of RobotStopTimerStart + 2000 might exceed 32 bits, will B4R use a variable for it that will fit it? I have no indication of what variable type will use so I made software to do it right no matter what.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…