Background:
The aim was to measure the wind direction and speed (m/s) passing through a moving bed of iron ore. The bed is ignited and air is sucked through the bed. The conveyor is 30m long and 4 m wide. An aluminium profile is placed across the conveyor and the "buggy" is moved to a series of points and the data collected. The data is used to determine if the suction is uniform over the width of the bed. The bed temperature is up to 1000°C but above the bed is room temperature. No cables can be used, therefore no power cable is possible.
Solution:
The buggy is made from aluminium with sides of styropor. Three wheels are free turning and the third is powered by a Nema23 format 5V motor, controlled by a RPi 3. The RPi software is written in B4J and the control/logger software on a tablet in B4A. The connection is via Bluetooth which works up to 10m. The sensor is mounted under the buggy (Black) and comes from the company Windsonic. This sensor is VERY sensitive. Walking past the sensor will give a measurement. The power for the buggy and sensor comes from a powerpack (15000 mAh) and can last up to 16 hours from one charge.
Photos:
The motor control is a L293 chip on a custom board. The B4J app is set to load at boot by including it in the "/etc/rc.local" file.
The main problem was finding a motor which would run at 5V and drive the buggy which has a total weight of 2.75 kg! The one I selected draws 2A which is the limit of the powerpack.
The mini aluminium profile is from the company Maker Beam for those who are interested.
B4J Code:
Just to complete the project, a few screenshots from the tablet and the code.
The complete B4A code is in the zip file.
The aim was to measure the wind direction and speed (m/s) passing through a moving bed of iron ore. The bed is ignited and air is sucked through the bed. The conveyor is 30m long and 4 m wide. An aluminium profile is placed across the conveyor and the "buggy" is moved to a series of points and the data collected. The data is used to determine if the suction is uniform over the width of the bed. The bed temperature is up to 1000°C but above the bed is room temperature. No cables can be used, therefore no power cable is possible.
Solution:
The buggy is made from aluminium with sides of styropor. Three wheels are free turning and the third is powered by a Nema23 format 5V motor, controlled by a RPi 3. The RPi software is written in B4J and the control/logger software on a tablet in B4A. The connection is via Bluetooth which works up to 10m. The sensor is mounted under the buggy (Black) and comes from the company Windsonic. This sensor is VERY sensitive. Walking past the sensor will give a measurement. The power for the buggy and sensor comes from a powerpack (15000 mAh) and can last up to 16 hours from one charge.
Photos:
The motor control is a L293 chip on a custom board. The B4J app is set to load at boot by including it in the "/etc/rc.local" file.
The main problem was finding a motor which would run at 5V and drive the buggy which has a total weight of 2.75 kg! The one I selected draws 2A which is the limit of the powerpack.
The mini aluminium profile is from the company Maker Beam for those who are interested.
B4J Code:
B4X:
'Non-UI application (console / server application)
#Region Project Attributes
#CommandLineArgs:
#MergeLibraries: True
#End Region
#AdditionalJar: bluecove-gpl-2.1.1-SNAPSHOT
#AdditionalJar: bluecove-bluez-2.1.1-SNAPSHOT
Sub Process_Globals
'variables for connection
Private bt As Bluetooth
Private astream As AsyncStreams 'connection to tablet
Private connected As Boolean=False 'bt connection or not
Private rcvStr As String 'data received
'variables for motor control
Type State (MotorOutput1 As Boolean, MotorOutput2 As Boolean, MotorOutput3 As Boolean, MotorOutput4 As Boolean)
Private timer1 As Timer
Private controller As GpioController
Private mA, mB, mAA, mBB, MotorEnable, RPiStatus As GpioPinDigitalOutput
Private states As List
Private currentStateIndex As Int
Private CW As Boolean=True
Private StepDelay As Int
Private SlowSpeed As Int=500
Private FastSpeed As Int=50
Private shl As Shell
Private Feedback As String
'Variables for windsonic
Private bstream As AsyncStreams 'connection to windsonic
Private myserial As Serial 'serial port for windsonic
Private uart_list As List 'list of ports
Private WSDataNotRequired As Boolean=True 'WS data is only required in sensor mode
End Sub
Sub AppStart (Args() As String)
controller.Initialize
MotorEnable.Initialize(0, False)
RPiStatus.Initialize(1, False) 'prepare green LED to show ready status of RPi
mA.Initialize(2, False) 'white A * Color coding for my motor, 6 pin *
mAA.Initialize(3, False) 'red A'
mB.Initialize(4, False) 'blue B
mBB.Initialize(5, False) 'yellow B'
' * Color coding for my 8 pin motor *
' red A
' red/white shorted with black/white
' black A'
' green B
' yellow/white sorted with green/white
' yellow B'
StepDelay=10
states.Initialize
states.Add(CreateState(True, True, False, False))
states.Add(CreateState(False, True, True,False))
states.Add(CreateState(False, False, True, True))
states.Add(CreateState(True, False, False, True))
'prepare timer for mtor control
timer1.Initialize("timer1", StepDelay)
timer1.Enabled = False
If CW=True Then
currentStateIndex = states.Size 'it will be incremented in Timer1_Tick
Else
currentStateIndex=-1
End If
'Timer1_Tick 'start with the first state
'Start bluetooth
bt.Initialize("bt")
If bt.IsEnabled = False Then
Log("Bluetooth not available1")
ExitApplication
End If
RPiStatus.State=True ' turn on green LED to show ready status of RPi
Log($"My address: ${GetBluetoothAddress}"$)
Log("***************************************************************************")
bt.Listen 'bt_Connected is called when connection is made
StartMessageLoop
End Sub
' Called when a command is received from tablet
Sub astream_NewData (Buffer() As Byte)
rcvStr = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
Log("***************************************************************************")
Log("Received command: " & rcvStr)
Log("***************************************************************************")
If connected=False Then Return 'cannot react to commands without connection
'Here we react to the commands from the tablet
'Motor and RPi commands
#Region
Select rcvStr
Case "forward"
CW=True
StepDelay=SlowSpeed
timer1.Interval=StepDelay
MotorEnable.State=True 'activate motor
timer1.Enabled=True
Case "fastforward"
CW=True
StepDelay=FastSpeed
timer1.Interval=StepDelay
MotorEnable.State=True
timer1.Enabled=True
Case "back"
CW=False
StepDelay=SlowSpeed
timer1.Interval=StepDelay
MotorEnable.State=True
timer1.Enabled=True
Case "fastback"
CW=False
StepDelay=FastSpeed
timer1.Interval=StepDelay
MotorEnable.State=True
timer1.Enabled=True
Case "stop" 'de-activate motor
timer1.Enabled=False
MotorEnable.State=False
Case "reboot" 'reboot the RPi
astream_Terminated 'reset GPIO
astream.Close
myserial.Close
shl.Initialize("shl", "reboot", Array As String())
shl.Run(-1)
Case "shutdown"
astream_Terminated 'reset GPIO
astream.Close
bstream.Close
myserial.Close
shl.Initialize("shl", "halt", Array As String())
shl.Run(-1)
#End Region
Case "MotorMode"
WSDataNotRequired=True
'bstream.Close
'myserial.Close
Case "SensorMode"
WSDataNotRequired=False
' Open com port for windsonic data
If bstream.IsInitialized Then Return
myserial.Initialize("")
uart_list = myserial.ListPorts
Dim Myport As Int
'Log("UART List: " & uart_list)
Myport=uart_list.IndexOf("/dev/ttyUSB0")
myserial.Open(uart_list.Get(Myport))
myserial.SetParams(9600,8,1,0)
Log("Com Port Initialized:" & uart_list.Get(Myport))
bstream.Initialize(myserial.GetInputStream,Null,"bstream")
End Select
' speed commands
#Region
If rcvStr.Contains("SlowSpeed") Then 'change slow speed, high time value command format: SlowSpeed 100
Dim lines() As String
lines=Regex.Split(" ", rcvStr)
SlowSpeed=lines(1)
Log("SlowSpeed set to " & SlowSpeed)
End If
If rcvStr.Contains("FastSpeed") Then 'change fast speed, low time value
Dim lines() As String
lines=Regex.Split(" ", rcvStr)
FastSpeed=lines(1)
Log("FastSpeed set to " & FastSpeed)
End If
#End Region
End Sub
' Called when com port gets new data from windsonic
Sub bstream_NewData (Buffer() As Byte)
If WSDataNotRequired=True Then Return 'ignore data coming from windsonic
rcvStr = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
Log("Sensor Data: " & rcvStr)
astream.Write(rcvStr.GetBytes("UTF8")) 'write to tablet
End Sub
'move motor
Sub Timer1_Tick
If CW=False Then
currentStateIndex=currentStateIndex-1
If currentStateIndex=-1 Then currentStateIndex = states.Size-1
Else
currentStateIndex = (currentStateIndex + 1) mod states.Size
End If
Dim st As State = states.Get(currentStateIndex)
mA.State = st.MotorOutput1
mB.State = st.MotorOutput2
mAA.State = st.MotorOutput3
mBB.state = st.MotorOutput4
Feedback="step " & CW 'Comand=STEP TRUE or STEP FALSE
Feedback=Feedback.ToUpperCase
Log(Feedback)
astream.Write(Feedback.GetBytes("UTF8")) 'send step command to tablet
End Sub
'setup states in a list
Sub CreateState(Motor1 As Boolean, Motor2 As Boolean, Motor3 As Boolean, Motor4 As Boolean) As State
' Motor connection A B A' B'
Dim st As State
st.Initialize
st.MotorOutput1 = Motor1
st.MotorOutput2 = Motor2
st.MotorOutput3 = Motor3
st.MotorOutput4 = Motor4
Return st
End Sub
' If bt is connected, setup astream to tablet
Sub bt_Connected (Success As Boolean, Connection As BluetoothConnection)
If Success Then
If astream.IsInitialized Then
astream.Close
End If
Log($"Connected to: ${Connection.Name} - ${Connection.MacAddress}"$)
Log("***************************************************************************")
'astream is the connection to tablet, works in both directions.
astream.Initialize(Connection.InputStream, Connection.OutputStream, "astream")
bt.Listen
connected=True
Else
Log("Error connecting...")
End If
End Sub
'Trap errors
Sub astream_Error
astream_Terminated
End Sub
Sub astream_Terminated
'bluetooth connection has been lost, reset the GPIO
RPiStatus.State=False
MotorEnable.State=False
mA.State=False
mAA.State=False
mB.State=False
mBB.State=False
Log("GPIO has been reset!")
End Sub
Sub GetBluetoothAddress As String
Dim jo As JavaObject = bt
Dim raw As String = jo.GetFieldJO("device").RunMethod("getBluetoothAddress", Null)
Dim sb As StringBuilder
sb.Initialize
For i = 0 To raw.Length - 1 Step 2
If sb.Length > 0 Then sb.Append(":")
sb.Append(raw.SubString2(i, i + 2))
Next
Return sb.ToString
End Sub
Just to complete the project, a few screenshots from the tablet and the code.
B4X:
#Region Project Attributes
#ApplicationLabel: Buggy remote Windsonic
#VersionCode: 1
#VersionName:
'SupportedOrientations possible values: unspecified, landscape or portrait.
#SupportedOrientations: landscape
#CanInstallToExternalStorage: False
#End Region
#Region Activity Attributes
#FullScreen: False
#IncludeTitle: True
#End Region
Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
Dim astream As AsyncStreams
Dim serial1 As Serial
Dim connected As Boolean =False
Dim Timer1 As Timer
End Sub
Sub Globals
'These global variables will be redeclared each time the activity is created.
'These variables can only be accessed from this module.
'
'These variables are used for the motor control
Dim btn_connect As Button
Dim btn_Quit As Button
Dim iv_back As ImageView
Dim iv_fback As ImageView
Dim iv_fforward As ImageView
Dim iv_forward As ImageView
Dim iv_stop As ImageView
Dim btn_HaltRpi As Button
Dim btn_RebootRPi As Button
Dim btn_Zero As Button
Dim Label4 As Label
Dim lbl_Distance As Label
Dim lbl_MaxDistance As Label
Dim lbl_MinDistance As Label
Dim sb_Distance As SeekBar
Dim btn_Sensor As Button
Dim rcvStr As String
Dim BuggyPosition As Int=0
Dim btn_SendFast As Button
Dim btn_SendSlow As Button
Dim edt_Fast As EditText
Dim edt_Slow As EditText
Dim lbl_SpeedFast As Label
Dim lbl_SpeedSlow As Label
Dim st, ft As Int
Dim ss, fs As Double
'
'These variables are used for the data and graph
Dim pnlData As Panel
Dim btn_CreateNewFile As Button
Dim btn_Motor As Button
Dim btn_StartStop As Button
Dim Label1 As Label
Dim Label2 As Label
Dim Label4 As Label
Dim Label5 As Label
Dim Label6 As Label
Dim lbl_Connected As Label
Dim lbl_Direction As Label
Dim lbl_ElapsedTime As Label
Dim lbl_FileName As Label
Dim lbl_LoggerStatus As Label
Dim lbl_Speed As Label
Dim LogFilename As String
Dim FileDirectory As String
Dim StartTime As Long
Dim ElapsedTime As String
Dim Writer As TextWriter
Dim NewFileCreated As Boolean=False
Dim rcvStr As String
' These are required for the graph
Dim pnlGraph As Panel
Dim bufsize As Int = 20 'set the data buffer size here i.e how many values to display in the plot area was 180
Dim xlab(bufsize) As String
Dim lc1 As RealTimeLineChart
Dim xlabeltrack As Int = 0
Dim DebugMode As Boolean=True
Dim btn_Debug As ToggleButton
Dim pnlMenu As Panel
Dim btnGraph As Button
Dim Label7 As Label
Dim LoggerStatus As Boolean=False
Dim pnl_back As Panel
Dim pnl_fback As Panel
Dim pnl_fforward As Panel
Dim pnl_forward As Panel
Dim pnl_stop As Panel
Dim OneStep As Double=1.195 ' mm per step rotation
Dim motorsteps As Int=0 'used to debug distance
End Sub
Sub Activity_Create(FirstTime As Boolean)
'Do not forget to load the layout file created with the visual designer. For example:
'Activity.LoadLayout("Layout1")
Activity.LoadLayout("layout1")
pnlData.Initialize("")
Activity.AddView(pnlData,0,0,Activity.Width,Activity.Height) 'add data panel to screen
pnlData.LoadLayout("layout2") 'load data screen into panel
pnlData.Visible=False 'and hide it.
If serial1.IsInitialized Then serial1.Disconnect
If FirstTime Then
serial1.Initialize("serial") 'prepare serial connection via bluetooth
Timer1.Initialize("timer1",1000)
End If
btn_connect.TextColor=Colors.red 'set not connected
lbl_Distance.Text=BuggyPosition
btn_Debug.Checked=DebugMode
'set default timings
st=45
edt_Slow.Text=st
' ss=(1000/st)*OneStep/10
ss=CalcSpeed(st)
lbl_SpeedSlow.Text=NumberFormat(ss,1,2) & " cm/s"
ft=15
edt_Fast.Text=ft
' fs=(1000/ft)*OneStep/10
fs=CalcSpeed(ft)
lbl_SpeedFast.Text=NumberFormat(fs,1,2) & " cm/s"
'Setup data screen
PrepareDataScreen
pnl_stop.Color=Colors.Green
End Sub
Sub CalcSpeed (s As Double) As Double
Return (1000/s)*OneStep/10
End Sub
' Connect via bluetooth - done
Sub btn_connect_Click
Log("Button connect")
If connected=False Then
Try
' Get a map of the paired devices
Dim PairedDevices As Map
PairedDevices = serial1.GetPairedDevices
Dim l As List
l.Initialize
For i = 0 To PairedDevices.Size - 1
l.Add(PairedDevices.GetKeyAt(i))
Next
Dim Res As Int
Res = InputList(l, "Choose device", -1) 'show list with paired devices
If Res <> DialogResponse.CANCEL Then
Log("Trying to connect to " & PairedDevices.Get(l.Get(Res)))
serial1.Connect(PairedDevices.Get(l.Get(Res))) 'convert the name to mac address and connect
End If
Catch
Log(LastException)
ToastMessageShow(LastException.Message, True)
End Try
End If
End Sub
' If bluetooth serial connect is successfull, then open stream and update UI - done
Sub Serial_Connected (Success As Boolean)
Log($"Connected ${Success}"$)
If Success Then
If astream.IsInitialized Then astream.Close
astream.Initialize(serial1.InputStream, serial1.OutputStream, "astream")
connected = True
Log("Stream opened")
btn_connect.TextColor=Colors.Green
Else
Msgbox("Bluetooth connection failed.","Error")
End If
End Sub
' ****************************************************************
' Buggy controls - done
#Region
Sub iv_forward_Click
If astream.IsInitialized=False Then Return
astream.Write("forward".GetBytes("UTF8"))
Log("Sent command: forward")
ResetImageBorder
pnl_forward.Color=Colors.Green
End Sub
Sub iv_fforward_Click
If astream.IsInitialized=False Then Return
astream.Write("fastforward".GetBytes("UTF8"))
Log("Sent command: fastforward")
ResetImageBorder
pnl_fforward.Color=Colors.Green
End Sub
Sub iv_fback_Click
If astream.IsInitialized=False Then Return
astream.Write("fastback".GetBytes("UTF8"))
Log("Sent command: fastback")
ResetImageBorder
pnl_fback.Color=Colors.Green
End Sub
Sub iv_back_Click
If astream.IsInitialized=False Then Return
astream.Write("back".GetBytes("UTF8"))
Log("Sent command: back")
ResetImageBorder
pnl_back.Color=Colors.Green
End Sub
Sub iv_stop_Click
If astream.IsInitialized=False Then Return
astream.Write("stop".GetBytes("UTF8"))
Log("Sent command: stop")
ResetImageBorder
pnl_stop.Color=Colors.Green
' Log("Steps moved: " & motorsteps)
End Sub
Sub ResetImageBorder
pnl_forward.Color=Colors.red
pnl_fforward.Color=Colors.red
pnl_fback.Color=Colors.red
pnl_back.Color=Colors.red
pnl_stop.Color=Colors.red
End Sub
#End Region
'RPi commands - done
#Region
' Reboot the RPi
Sub btn_RebootRPi_Click
If astream.IsInitialized=False Then Return 'cannot reboot without a connection
Dim result As Int
result=Msgbox2( "Reboot RPi?","Confirmation required.","Yes","","No",Null)
If result=DialogResponse.NEGATIVE Then
Return
End If
astream.Write("reboot".GetBytes("UTF8"))
Log("Sent command: reboot RPi")
btn_connect.TextColor=Colors.red
'tidy up
If astream.IsInitialized Then astream.Close
If serial1.IsInitialized Then serial1.Disconnect
End Sub
' Shutdown the RPi
Sub btn_HaltRpi_Click
If astream.IsInitialized=False Then Return
Dim result As Int
result=Msgbox2( "Shutdown RPi?","Confirmation required.","Yes","","No",Null)
If result=DialogResponse.NEGATIVE Then
Return
End If
astream.Write("shutdown".GetBytes("UTF8"))
Log("Sent command: shutdown RPi")
btn_connect.TextColor=Colors.red
'tidy up
If astream.IsInitialized Then astream.Close
If serial1.IsInitialized Then serial1.Disconnect
End Sub
' Change the slow speed
Sub edt_Slow_EnterPressed
st=edt_Slow.Text
If st<ft Or st>45 Then
ToastMessageShow("Slow speed cannot be less than fast speed or is too slow...using default",False)
edt_Slow.Text="45"
st=edt_Slow.Text
End If
ss=CalcSpeed(st)
lbl_SpeedSlow.Text=NumberFormat(ss,1,1) & " cm/s"
End Sub
' Change the fast speed
Sub edt_Fast_EnterPressed
ft=edt_Fast.Text
If ft>st Or ft<15 Then
ToastMessageShow("Fast speed MUST be less than slow speed or is too fast...using default",False)
edt_Fast.Text="15"
ft=edt_Fast.Text
End If
fs=CalcSpeed(ft)
lbl_SpeedFast.Text=NumberFormat(fs,1,1) & " cm/s"
End Sub
' Send new spped to RPi
Sub btn_SendSlow_Click
If astream.IsInitialized=False Then Return
Dim t As String
t="SlowSpeed " & st
astream.Write(t.GetBytes("UTF8"))
Log("Sent command: " & t)
End Sub
' Send new spped to RPi
Sub btn_SendFast_Click
If astream.IsInitialized=False Then Return
Dim t As String
t="FastSpeed " & ft
astream.Write(t.GetBytes("UTF8"))
Log("Sent command: " & t)
End Sub
#End Region
'click events for buttons
' Set current position to zero
Sub btn_Zero_Click
Dim result As Int
result=Msgbox2( "Reset position to zero?","Confirmation required.","Yes","","No",Null)
If result=DialogResponse.NEGATIVE Then
Return
End If
BuggyPosition=0
lbl_Distance.Text=NumberFormat(BuggyPosition/1000,1,1)
sb_Distance.Value=NumberFormat(BuggyPosition/1000,1,0)
motorsteps=0
End Sub
' Switch to sensor mode still to do!
Sub btn_Sensor_Click
'switch to sensor data screen
pnlData.Visible=True
If connected=True Then
lbl_Connected.Color=Colors.Green
lbl_Connected.Text="Connected"
astream.Write("SensorMode".GetBytes("UTF8")) 'activate windsonic
Log("Sent command: " & "SensorMode")
End If
Timer1.Enabled=True
End Sub
' create new file based on date and time
Sub btn_CreateNewFile_Click
lbl_FileName.Text=CreateFileName
NewFileCreated=True
End Sub
' create a filename from date and time
Sub CreateFileName () As String
Dim d, t As String
DateTime.DateFormat = "yyyyMMdd"
DateTime.TimeFormat="HHmm"
d = DateTime.Date(DateTime.Now)
t = DateTime.Time(DateTime.Now)
LogFilename= d & "-" & t & ".txt"
Return LogFilename
End Sub
' Start logger
Sub btn_StartStop_Click
' Cannot start looger if we are not connected or no filename
If NewFileCreated=False Then
Msgbox("Please create a file first!.","Error")
Return
End If
If connected=False Then
Msgbox("In debug mode, data cannot be logged!","Error")
Return
End If
If LoggerStatus=False Then 'Logger is off, turn on
LoggerStatus=True
lbl_LoggerStatus.Color=Colors.Green 'change background color
btn_StartStop.Text="Stop Logger" 'change button text
Timer1.Enabled=True 'start timer
DateTime.TimeFormat="HH:mm:ss"
StartTime=DateTime.Now 'Store start time for logger
Writer.Initialize(File.OpenOutput(FileDirectory, LogFilename, True)) 'Open stream for ascii file
If DebugMode=True Then 'make sure we do not log in debug mode
DebugMode=False
btn_Debug.Checked=False
End If
ScreenShot
Else
LoggerStatus=False
lbl_LoggerStatus.Color=Colors.Red
btn_StartStop.Text="Start Logger"
Writer.Close 'Close logger file
Timer1.Enabled=False
Timer1.Enabled=True
End If
End Sub
'Turn on/off graph panel
Sub btnGraph_Click
pnlGraph.Visible=Not(pnlGraph.Visible)
End Sub
Sub btn_Debug_CheckedChange(Checked As Boolean)
If connected=False Then
btn_Debug.Checked=True
Return 'Cannot switch to sensor when not connected
End If
DebugMode=Not(DebugMode)
btn_Debug.Checked=DebugMode
If DebugMode Then
Log("Debug Mode")
LoggerStatus=False
lbl_LoggerStatus.Color=Colors.Red
btn_StartStop.Text="Start Logger"
If LoggerStatus Then Writer.Close 'Close logger file if we are logging
Timer1.Enabled=False
Timer1.Enabled=True
Else
Log("Sensor Mode")
End If
End Sub
'return to buggy control
Sub btn_Motor_Click
Dim result As Int
result=Msgbox2("Return to buggy control?","Confirmation required.","Yes","","No",Null)
If result<>DialogResponse.POSITIVE Then
Return
End If
If connected=True Then
astream.Write("MotorMode".GetBytes("UTF8"))
Log("Sent command: " & "MotorMode")
' reset to debug mode
If LoggerStatus Then Writer.Close 'Close logger file
LoggerStatus=False
lbl_LoggerStatus.Color=Colors.Red
btn_StartStop.Text="Start Logger"
If DebugMode=False Then 'make sure we do not log in debug mode
DebugMode=True 'timer1 can continue as we are in debug mode
btn_Debug.Checked=True
End If
NewFileCreated=False 'reset new file
End If
pnlData.Visible=False
End Sub
Sub btn_Quit_Click
Dim result As Int
result=Msgbox2( "Do you really want to exit?","Confirmation required.","Yes","","No",Null)
If result=DialogResponse.NEGATIVE Then
Return
End If
If astream.IsInitialized Then astream.Close
If serial1.IsInitialized Then serial1.Disconnect
Activity.Finish
End Sub
' ****************************************************************
' End of commands
' ****************************************************************
' Called when data is received from RPi
' RPi sends a step command when a step is made or it sends data
Sub astream_NewData (Buffer() As Byte)
rcvStr = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
Select rcvStr
Case "STEP TRUE"
Log("moved forward")
BuggyPosition=BuggyPosition+OneStep
lbl_Distance.Text=NumberFormat(BuggyPosition/10,1,1) & " cm"
sb_Distance.Value=NumberFormat(BuggyPosition/10,1,0)
motorsteps=motorsteps+1
Log("Steps moved: " & motorsteps)
' If BuggyPosition>500 Then
' ToastMessageShow("Forward movement limited to 500cm!",True)
' iv_stop_Click
' End If
Case "STEP FALSE"
Log("moved back")
BuggyPosition=BuggyPosition-OneStep
lbl_Distance.Text=NumberFormat(BuggyPosition/10,1,1) & " cm"
sb_Distance.Value=NumberFormat(BuggyPosition/10,1,0)
motorsteps=motorsteps-1
Log("Steps moved: " & motorsteps)
' If BuggyPosition<0 Then
' ToastMessageShow("Cannot move less than 0cm!",True)
' iv_stop_Click
' End If
Case Else
' otherwise we have received data from the windsonic
'Log("Received data: " & rcvStr)
If DebugMode=False Then 'only update if we are in sensor mode
Dim lines() As String
lines=Regex.Split(",", rcvStr)
If lines.Length=6 Then
lbl_Speed.Text=lines(2)
lbl_Direction.Text=lines(1)
End If
End If
End Select
End Sub
' Used in demo mode AND real mode. Calc elapsed time, update UI
Sub Timer1_Tick
'**************************************************************************************************************
If DebugMode Then ' use random data
lbl_Speed.Text=NumberFormat(Rnd(100,200)/100,0, 2) 'speed between 1 and 2 m/s
lbl_Direction.Text=Rnd(180,360) 'direction between 180 and 360 degrees
'**************************************************************************************************************
Else
If LoggerStatus=True Then
Dim t, String1 As String
DateTime.TimeFormat="HH:mm:ss"
t = DateTime.Time(DateTime.Now)
ElapsedTime=ConvertTicksToTimeString(DateTime.Now-StartTime) 'calculate elapsed time
lbl_ElapsedTime.Text=ElapsedTime 'update UI
'This is one line in text file
String1=t & "," & ElapsedTime & "," & lbl_Speed.Text & "," & lbl_Direction.Text & "," & lbl_Distance.Text & Chr(13)
Log(String1)
Writer.WriteLine(String1) 'write to file
End If
End If
'**************************************************************************************************************
' chart code
#Region
Dim Speed, Direction As Float
Speed=lbl_Speed.Text
Direction=lbl_Direction.Text/180
lc1.addData(Speed,Direction,0,0,0)
' If xlabeltrack = bufsize + 1 Then
' t.Enabled = False
' lc1.ClearAllData 'THIS WILL CLEAR THE DATA
' End If
'************************ If you comment this code then the x-axis labels will be the index of the buffer
xlabeltrack = xlabeltrack + 1
If xlabeltrack > bufsize Then
xlab = shiftarray(xlab)
xlab(bufsize - 1) = "x-" & xlabeltrack
lc1.XAxisLabels = xlab
End If
xlab(bufsize - 1) = "x-" & xlabeltrack
'**************************************************************************************************************
#End Region
End Sub
Sub astream_Error
astream_Terminated
End Sub
Sub astream_Terminated
'oops we lost the bluetooth connection
Msgbox("Bluetooth connection lost","Error")
'Try and reconnect
If serial1.IsInitialized Then
serial1.Disconnect
'serial1.Connect(txtMAC)
End If
btn_connect.TextColor=Colors.red
End Sub
Sub Activity_Resume
Log("Serial1 is initialised: " & serial1.IsInitialized)
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
Sub PrepareGraph
lc1.GraphTitleColor = Colors.White
lc1.GraphTitleSkewX = -0.15
lc1.GraphTitleBold = True
lc1.GraphTitleTextSize = 20.0
lc1.GraphPlotAreaBackgroundColor = Colors.DarkGray 'this will paint the plotting area DarkGray regardless of what GraphBackgroundColor has been set to
lc1.GraphBackgroundColor = Colors.Transparent 'this will paint everything within the outer frame to be white
lc1.GraphFrameColor = Colors.Red 'this adjusts only the outer frame color
lc1.GraphFrameWidth = 2.0
lc1.GraphBufferSize = bufsize
lc1.GraphTitle = "Real Time Data"
lc1.DomainLabelColor = Colors.Cyan
lc1.DomainLabelTextSize = 20
lc1.DomianLabel = ""
lc1.YaxisRangeMode = lc1.YaxisMode_FIXED 'the other option is FIXED
lc1.YaxisRange(0, 2)
lc1.YaxisDivisions = 4
lc1.YaxisLabelTicks = 1
lc1.YaxisShowZero = True
lc1.YaxisTitleTextSize = 20.0
lc1.YaxisTitleColor = Colors.Green
lc1.YaxisGridLineColor = Colors.Yellow
lc1.YaxisLabelTextSize = 15
lc1.YaxisLabelColor = Colors.Green
lc1.YaxisLabelOrientation = 0
lc1.YaxisTitle = "[m/s]"
'************************ If you comment this code then the x-axis labels will be the index value of the buffer
' For i = 0 To bufsize - 1
' 'xlab(i) = "x-" & i
' xlab(i) = TimeInSeconds
' Next
' lc1.XAxisLabels = xlab
'*************************************************************************************************************
lc1.XaxisLabelTextSize = 15
lc1.XaxisLabelTextColor = Colors.Cyan
lc1.XaxisGridLineColor = Colors.Yellow
lc1.XaxisLabelOrientation = 0
lc1.XaxisDivisions = 19 'was 59
lc1.XaxisLabelTicks = 19
lc1.LegendTextSize = 15.0
lc1.LegendTextColor = Colors.White
lc1.LegendBackgroundColor = Colors.Transparent
'setup for Line 1
lc1.Line_1_LineColor = Colors.green
lc1.Line_1_LineWidth = 2.0
lc1.Line_1_DrawDash = True
lc1.Line_1_LegendText = "Speed"
'setup for Line 2
lc1.Line_2_LineColor = Colors.red
lc1.Line_2_LineWidth = 2.0
lc1.Line_2_DrawDash = False
lc1.Line_2_LegendText = "Direction /180"
lc1.NumberOfLineCharts = 2
lc1.DrawTheGraphs
End Sub
'required for graph
Sub shiftarray (oldarray() As String) As String()
Dim newarray(bufsize)
For i = 0 To bufsize - 2
newarray(i) = oldarray(i + 1)
Next
Return newarray
End Sub
' Used to calc elapsed time
Sub ConvertTicksToTimeString(t As Long) As String
Dim hours, minutes, seconds As Int
hours = t / DateTime.TicksPerHour
minutes = (t Mod DateTime.TicksPerHour) / DateTime.TicksPerMinute
seconds = (t Mod DateTime.TicksPerMinute) / DateTime.TicksPerSecond
'TimeInSeconds=(hours*3600)+(minutes*60)+seconds
Return NumberFormat(hours, 2, 0) & ":" _
& NumberFormat(minutes, 2, 0) & ":" & NumberFormat(seconds, 2, 0)
End Sub
' Make a screenshot with date and time stamp
Sub ScreenShot
' Take a screenshot.
Dim Obj1, Obj2 As Reflector
Dim bmp As Bitmap
Dim c As Canvas
Dim Fname As String
Obj1.Target = Obj1.GetActivityBA
Obj1.Target = Obj1.GetField("vg")
bmp.InitializeMutable(Activity.Width, Activity.Height)
c.Initialize2(bmp)
Dim args(1) As Object
Dim types(1) As String
Obj2.Target = c
Obj2.Target = Obj2.GetField("canvas")
args(0) = Obj2.Target
types(0) = "android.graphics.Canvas"
Obj1.RunMethod4("draw", args, types)
Dim Out As OutputStream
Fname=CreateFileName
Fname=Fname.Replace(".txt", ".png")
Out = File.OpenOutput(File.DirRootExternal, Fname, False)
bmp.WriteToStream(Out, 100, "PNG")
Out.Close
End Sub
Sub PrepareDataScreen
' Make directory to hold logger files
If File.IsDirectory(File.DirRootExternal,"windsonic/") = False Then
File.MakeDir(File.DirRootExternal,"windsonic")
Log("Directory created!")
End If
pnlGraph.Visible=False
FileDirectory=File.DirRootExternal & "/windsonic/"
Log(FileDirectory)
lbl_LoggerStatus.Color=Colors.Red
lbl_FileName.Color=Colors.White
lbl_FileName.TextColor=Colors.Black
lbl_FileName.Text="Please create new file to start"
lbl_Speed.Color=Colors.White
lbl_Speed.TextColor=Colors.Black
lbl_Direction.Color=Colors.White
lbl_Direction.TextColor=Colors.Black
lbl_ElapsedTime.Color=Colors.White
lbl_ElapsedTime.TextColor=Colors.Black
Activity.Title="Windsonic Datalogger Version 1"
PrepareGraph
If DebugMode Then
DateTime.TimeFormat="HH:mm:ss"
StartTime=DateTime.Now
'Timer1.Enabled=True
End If
lc1.START 'Start graph
End Sub
The complete B4A code is in the zip file.
Attachments
Last edited: