mc-Things
mc-Products => mc-Module => Topic started by: Nick_W on August 17, 2016, 09:42:58 am
-
I'm having some problems with my BME280 module, so I tried some experiments with the internal Temperature Sensor (to eliminate external errors).
I don't seem to be able to define an I2c object as shared (might not be just I2c, but this is what I am testing).
For example, this code works (the MQTT class just makes MQTT stuff easier):
Class MQTT
Shared mcUIDString As String
Shared Sub Publish(topic As String, value As String)
If mcUIDString = Nothing Then
mcUIDString = Device.mcUID().ToString("X8")
End If
Dim text_string As ListOfByte = New ListOfByte()
text_string.Add(value)
Lplan.Publish("MCThings/" + mcUIDString + "/" + topic, text_string)
End Sub
Shared Sub Publish(topic As String, value As Object)
Dim text As String = value.ToString()
If mcUIDString = Nothing Then
mcUIDString = Device.mcUID().ToString("X8")
End If
Dim text_string As ListOfByte = New ListOfByte()
text_string.Add(text)
Lplan.Publish("MCThings/" + mcUIDString + "/" + topic, text_string)
End Sub
Shared Sub Publish_exact(topic As String, text As String)
Dim text_String As ListOfByte = New ListOfByte()
text_String.Add(text)
Lplan.Publish(topic, text_String)
End Sub
Shared Sub BeaconPublish(data_Type As Byte, data As Integer)
data = data & 0x0fffffff //blank top byte (can only send 24 bits maximum)
Dim hi_byte As Byte = ((data >> 16) & 0xff).ToByte()
Dim mid_byte As Byte = ((data >> 8) & 0xff).ToByte()
Dim low_byte As Byte = (data & 0xff).ToByte()
Dim beconData As ListOfByte = New ListOfByte()
beconData.Add(data_Type)
beconData.Add(hi_byte)
beconData.Add(mid_byte)
beconData.Add(low_byte)
Lplan.SetBeaconData(beconData)
Lplan.SendBeacon()
End Sub
Shared Sub Subscribe(topic As String)
Lplan.Subscribe(topic)
End Sub
End Class
Class Main
//Shared Internal_Temp As TempSensor
Shared booted As Boolean
Shared count As Integer
Shared Event Boot()
booted = True
count = 5
//Internal_Temp = New TempSensor()
End Event
Shared Event Publish_Values() RaiseEvent Every 10 Seconds
LedGreen = True
If booted Then
MQTT.Publish("Status", "Booted")
booted = False
End If
Dim Internal_Temp As TempSensor = New TempSensor()
Dim TempC As Float = Internal_Temp.GetTemp()
MQTT.Publish("Temperature", TempC)
Dim Uptime As Integer = Device.Uptime()
MQTT.Publish("Uptime", Uptime)
Dim BattVolt As Integer = Device.BatteryVoltage()
MQTT.Publish("BatteryVoltage", BattVolt)
count = count + 1
MQTT.Publish("Count", count)
LedGreen = False
End Event
End Class
Class TempSensor
// Function returns the temperature in degree celcius or
// Float.NaN if something is wrong
Public sensor As I2c
Public Sub New()
sensor = I2c.Create(400000, Pin.SCL, Pin.SDA, 0x48)
End Sub
Public Function GetTemp() As Float
// Define the properties of the I2C peripheral and device address
//Dim sensor As I2c
//sensor = I2c.Create(400000, Pin.SCL, Pin.SDA, 0x48)
// Power up the sensor and give it some time to settle
Device.EnableTempSensor()
Thread.Sleep(40000) // See page 13 of the datasheet
// Read the sensor (only 2 bytes to read
Dim res As ListOfByte = sensor.Read(2)
// See Tmp102 documentation how to interpret the data (page 8)
Dim temp As Float = Float.NaN
If res <> Nothing Then
// Shift the partial part to the right nibble
Dim part As Float = res(1) >> 4
// Temperature partial is 1/16*n where n is between 0 and 15
part = part / 16
// Sign extend the byte to an integer
temp = res(0).SignExtend() + part
Else
LedRed = True
Thread.Sleep(50000)
LedRed = False
End If
// power off
Device.DisableTempSensor()
Return temp
End Function
Shared Function GetDieTemp() As Float
// Just get the temperature and return
Return Device.TempDie
End Function
Shared Function ToFarenheit(celcius As Float) As Float
Return (celcius * 9) / 5 + 32
End Function
Shared Function ToCelcius(farenheit As Float) As Float
Return (farenheit - 32) * 5 / 9
End Function
End Class
Note the "Dim Internal_Temp As TempSensor = New TempSensor()" in Class Main.
If I Try to Make this a shared variable of class main, it causes the module to reset. This does not work:
Class MQTT
Shared mcUIDString As String
Shared Sub Publish(topic As String, value As String)
If mcUIDString = Nothing Then
mcUIDString = Device.mcUID().ToString("X8")
End If
Dim text_string As ListOfByte = New ListOfByte()
text_string.Add(value)
Lplan.Publish("MCThings/" + mcUIDString + "/" + topic, text_string)
End Sub
Shared Sub Publish(topic As String, value As Object)
Dim text As String = value.ToString()
If mcUIDString = Nothing Then
mcUIDString = Device.mcUID().ToString("X8")
End If
Dim text_string As ListOfByte = New ListOfByte()
text_string.Add(text)
Lplan.Publish("MCThings/" + mcUIDString + "/" + topic, text_string)
End Sub
Shared Sub Publish_exact(topic As String, text As String)
Dim text_String As ListOfByte = New ListOfByte()
text_String.Add(text)
Lplan.Publish(topic, text_String)
End Sub
Shared Sub BeaconPublish(data_Type As Byte, data As Integer)
data = data & 0x0fffffff //blank top byte (can only send 24 bits maximum)
Dim hi_byte As Byte = ((data >> 16) & 0xff).ToByte()
Dim mid_byte As Byte = ((data >> 8) & 0xff).ToByte()
Dim low_byte As Byte = (data & 0xff).ToByte()
Dim beconData As ListOfByte = New ListOfByte()
beconData.Add(data_Type)
beconData.Add(hi_byte)
beconData.Add(mid_byte)
beconData.Add(low_byte)
Lplan.SetBeaconData(beconData)
Lplan.SendBeacon()
End Sub
Shared Sub Subscribe(topic As String)
Lplan.Subscribe(topic)
End Sub
End Class
Class Main
Shared Internal_Temp As TempSensor
Shared booted As Boolean
Shared count As Integer
Shared Event Boot()
booted = True
count = 5
Internal_Temp = New TempSensor()
End Event
Shared Event Publish_Values() RaiseEvent Every 10 Seconds
LedGreen = True
If booted Then
MQTT.Publish("Status", "Booted")
booted = False
End If
//Dim Internal_Temp As TempSensor = New TempSensor()
Dim TempC As Float = Internal_Temp.GetTemp()
MQTT.Publish("Temperature", TempC)
Dim Uptime As Integer = Device.Uptime()
MQTT.Publish("Uptime", Uptime)
Dim BattVolt As Integer = Device.BatteryVoltage()
MQTT.Publish("BatteryVoltage", BattVolt)
count = count + 1
MQTT.Publish("Count", count)
LedGreen = False
End Event
End Class
Class TempSensor
// Function returns the temperature in degree celcius or
// Float.NaN if something is wrong
Public sensor As I2c
Public Sub New()
sensor = I2c.Create(400000, Pin.SCL, Pin.SDA, 0x48)
End Sub
Public Function GetTemp() As Float
// Define the properties of the I2C peripheral and device address
//Dim sensor As I2c
//sensor = I2c.Create(400000, Pin.SCL, Pin.SDA, 0x48)
// Power up the sensor and give it some time to settle
Device.EnableTempSensor()
Thread.Sleep(40000) // See page 13 of the datasheet
// Read the sensor (only 2 bytes to read
Dim res As ListOfByte = sensor.Read(2)
// See Tmp102 documentation how to interpret the data (page 8)
Dim temp As Float = Float.NaN
If res <> Nothing Then
// Shift the partial part to the right nibble
Dim part As Float = res(1) >> 4
// Temperature partial is 1/16*n where n is between 0 and 15
part = part / 16
// Sign extend the byte to an integer
temp = res(0).SignExtend() + part
Else
LedRed = True
Thread.Sleep(50000)
LedRed = False
End If
// power off
Device.DisableTempSensor()
Return temp
End Function
Shared Function GetDieTemp() As Float
// Just get the temperature and return
Return Device.TempDie
End Function
Shared Function ToFarenheit(celcius As Float) As Float
Return (celcius * 9) / 5 + 32
End Function
Shared Function ToCelcius(farenheit As Float) As Float
Return (farenheit - 32) * 5 / 9
End Function
End Class
So if I change Internal_sensor from a local variable to a Shared variable, the module resets. What am I doing wrong? The TempSensor object should be created at boot, and should persist as a shared variable of class Main, but I'm guessing from the resets, it is being destroyed. No errors in MCStudio, and builds fine.
I'm wanting to do this as I want to create a BME280 object (one per sensor), but it seems that I have to create a new object every time I want to use it. I can't make a persistent I2C object.
Any suggestions would be appreciated.
-
Is this problem related to the "odd memory behavior" problem?
-
Not as such,
I'm trying to create a persistent I2C object (persists between timed events). But I can't get it to work.
The object works if you create it in the event. If you create it at boot (or any other time), it doesn't work in Shared Events (resets). I was looking at memory to see what was happening, but maybe got lead astray by the "odd memory behavior".
So ignoring weird memory things, how do you create a shared I2C object, that can be used in a Shared event without having to re-create it every time?
If I re-create it every time, then everything that is stored in the I2c module (calibration factors etc) have to be re-read into local variables each time you want to read the sensor. You also have to set up the resolution, filtering, period, etc. etc. Not really the point of a class.
I should be able to do this once (when the instance of the class is created as an object (in New)), then just call the readTemperature() method to read the I2C register and calculate the temperature or whatever.
I don't want to have to create a new object every time I want to read anything over I2C.
If I make everything Shared (ie don't use Public/Private at all), and don't create an instance of the object, it works - but then you can only use it for one sensor...
Any Suggestions?
-
We found the problem. I2C in some cases overwrites a shared variable.
We will fix it and we will try to get it out today.
-John-
-
Thanks John,
I now have the class working (with your pressure conversion function), so I'll integrate it into the rest of my program, and wait for the fix.
Thanks for the quick feedback.
-
John,
Tom sent me the binaries (7-365) I just loaded everything and it works ;D
I now have my persistent I2c object functioning for both internal temperature sensor, and external BME280 temp/humid/press sensor.
Thank you!
Now if I can just find out why it keeps running out of memory and resetting....