Wireless Mesh
Dr_Acula
Posts: 5,484
I've been wanting to build a wireless mesh for some time - I kind of like the idea of redundancy with a swarm of robots or nodes where the system works even if a few stop working, and the system works better if you add more nodes. See at the bottom for a screenshot.
I think the Propeller can do this.
Previously I have started building a few mesh networks, but invariably the code needs changing and it becomes difficult changing code on multiple nodes out in the field. So I've turned to testing it in a simulation first, and have found out all sorts of interesting things.
Let's assume a Propeller chip, and some sort of wireless module. There are many choices and prices one can use. For simplicity, assume a limited range, and that all nodes use the same frequency. Because of the limited range, parts of the mesh can be talking amongst themselves on the same frequency at the same time without interference, and indeed, there is an advantage here to having less range and less power.
The first task a new node has is to find its neighbours. It can send ping messages and over time, build up a table of the nodes it can reach reliably.
The next task is for any node to be able to send a message to any other node. The most efficient way to do this is with the minimum number of hops. To do this, there are several solutions, and a simple one is to build a "routing table" which lists every node's connection and works out the best route.
Well - I tried simulating that and the table got out of control. The number of possible routes goes up something like the factorial of the number of nodes. Fine for 3 nodes with 3x2x1=6 possible paths. Not so good with 20 nodes and 2432902008176640000 paths.
Of course, you can prune the paths, and with a sparse network there still might only be a handful of paths. But the pruning algorithms need a lot of memory and they take time to run. Plus they are kind of complicated to understand http://en.wikipedia.org/wiki/Dijkstra's_algorithm
So after a bit of research I found an intriguing algorithm based on a heat model. It gets a mention on page 3 http://www.ijcst.org/Volume3/Issue5/p15_3_5.pdf
Each node is a heat source, and each produces a different type of heat so you can track the heat from that node. To find a path to that node, simply hop to the hottest nearby node.
I've been playing around with a simulation. Multicast vs unicast packets. Sending nodes to sleep after they have transmitted. Adding a cooling algorithm based on thermodynamics. Working out the optimum number of hops before a packet dies. And the final code is rather simple and certainly something that a Propeller could run.
Take a packet of heat from the source node (joules), take percentage for yourself, then pick a random nearby node and send the rest on to that node. After n hops, the packet dies.
Send these packets out regularly, and over a period of time the nodes all reach the correct temperature such that a message injected at any random node can always find its way to the correct source. There is no routing table, and no need for lots of memory, and each node only works locally. Intriguingly, the heat does not spread out based on distance. It spreads out based on hops, which is what we are trying to optimise for.
Below is the simulation after it has run for a few minutes. The source node is A, and this uses a Black Body temperature scale, where about 6000K is white, temperatures below that are red, temperatures above that are blue. The picture is 1024 pixels wide, and nodes within 300 pixels of each other can talk to each other. All the locations are generated by a random number generator so lots of different configurations can be tested.
Nodes that are many hops away, like L, are the coldest. The fascinating thing is that node I, which is closer to A, is cooler than node T. This is because T has more surrounding nodes, so the packets bounce around more around T. It doesn't matter, because as can be seen from the list of local connections, any message reaching T can go straight to A and bypass I.
The vb.net code is below. Node data is in arrays, but in practice each node would only have its own local information. The simulation only allows transmitting data to local nodes, so there is nothing that can see the whole picture in the same way as this screenshot.
Very sparse networks do start to fail with this system as they form local hotspots and messages bounce around these local maxima. This can be mitigated by decreasing the number of hops before a packet dies, or by increasing the density of the mesh.
I guess the big lesson from this for me is not to try to build a mesh without simulating it fully first. But having simulated it, I can see how it is possible to translate the code over to Spin fairly easily. Need some floating point numbers, and need a simple packet protocol between nodes, probably along the lines of "open comms", "ack", "send data", "close comms".
Anyone here played around with wireless mesh networks?
I think the Propeller can do this.
Previously I have started building a few mesh networks, but invariably the code needs changing and it becomes difficult changing code on multiple nodes out in the field. So I've turned to testing it in a simulation first, and have found out all sorts of interesting things.
Let's assume a Propeller chip, and some sort of wireless module. There are many choices and prices one can use. For simplicity, assume a limited range, and that all nodes use the same frequency. Because of the limited range, parts of the mesh can be talking amongst themselves on the same frequency at the same time without interference, and indeed, there is an advantage here to having less range and less power.
The first task a new node has is to find its neighbours. It can send ping messages and over time, build up a table of the nodes it can reach reliably.
The next task is for any node to be able to send a message to any other node. The most efficient way to do this is with the minimum number of hops. To do this, there are several solutions, and a simple one is to build a "routing table" which lists every node's connection and works out the best route.
Well - I tried simulating that and the table got out of control. The number of possible routes goes up something like the factorial of the number of nodes. Fine for 3 nodes with 3x2x1=6 possible paths. Not so good with 20 nodes and 2432902008176640000 paths.
Of course, you can prune the paths, and with a sparse network there still might only be a handful of paths. But the pruning algorithms need a lot of memory and they take time to run. Plus they are kind of complicated to understand http://en.wikipedia.org/wiki/Dijkstra's_algorithm
So after a bit of research I found an intriguing algorithm based on a heat model. It gets a mention on page 3 http://www.ijcst.org/Volume3/Issue5/p15_3_5.pdf
Each node is a heat source, and each produces a different type of heat so you can track the heat from that node. To find a path to that node, simply hop to the hottest nearby node.
I've been playing around with a simulation. Multicast vs unicast packets. Sending nodes to sleep after they have transmitted. Adding a cooling algorithm based on thermodynamics. Working out the optimum number of hops before a packet dies. And the final code is rather simple and certainly something that a Propeller could run.
Take a packet of heat from the source node (joules), take percentage for yourself, then pick a random nearby node and send the rest on to that node. After n hops, the packet dies.
Send these packets out regularly, and over a period of time the nodes all reach the correct temperature such that a message injected at any random node can always find its way to the correct source. There is no routing table, and no need for lots of memory, and each node only works locally. Intriguingly, the heat does not spread out based on distance. It spreads out based on hops, which is what we are trying to optimise for.
Below is the simulation after it has run for a few minutes. The source node is A, and this uses a Black Body temperature scale, where about 6000K is white, temperatures below that are red, temperatures above that are blue. The picture is 1024 pixels wide, and nodes within 300 pixels of each other can talk to each other. All the locations are generated by a random number generator so lots of different configurations can be tested.
Nodes that are many hops away, like L, are the coldest. The fascinating thing is that node I, which is closer to A, is cooler than node T. This is because T has more surrounding nodes, so the packets bounce around more around T. It doesn't matter, because as can be seen from the list of local connections, any message reaching T can go straight to A and bypass I.
The vb.net code is below. Node data is in arrays, but in practice each node would only have its own local information. The simulation only allows transmitting data to local nodes, so there is nothing that can see the whole picture in the same way as this screenshot.
Very sparse networks do start to fail with this system as they form local hotspots and messages bounce around these local maxima. This can be mitigated by decreasing the number of hops before a packet dies, or by increasing the density of the mesh.
I guess the big lesson from this for me is not to try to build a mesh without simulating it fully first. But having simulated it, I can see how it is possible to translate the code over to Spin fairly easily. Need some floating point numbers, and need a simple packet protocol between nodes, probably along the lines of "open comms", "ack", "send data", "close comms".
Anyone here played around with wireless mesh networks?
Imports System.Math ' so can use Log Public Class Form1 ' Wireless mesh HEAT protocol Dim NodeX(20) As Integer ' x location Dim NodeY(20) As Integer ' y location Dim Friends(20) As String ' A=node 0, B=node1 etc Dim Temperature(20) As Single ' temp in kelvins Dim Inbox(20, 4) As Single ' inbox for messages Dim SendCounter As Integer Dim HopString As String Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim i As Integer For i = 0 To 19 NodeX(i) = Rnd() * 770 ' x - max value so doesn't overwrite the text boxes and buttons NodeY(i) = Rnd() * 680 ' y Next PictureBox1.Location = New Point(NodeX(0), NodeY(0)) PictureBox2.Location = New Point(NodeX(1), NodeY(1)) PictureBox3.Location = New Point(NodeX(2), NodeY(2)) PictureBox4.Location = New Point(NodeX(3), NodeY(3)) PictureBox5.Location = New Point(NodeX(4), NodeY(4)) PictureBox6.Location = New Point(NodeX(5), NodeY(5)) PictureBox7.Location = New Point(NodeX(6), NodeY(6)) PictureBox8.Location = New Point(NodeX(7), NodeY(7)) PictureBox9.Location = New Point(NodeX(8), NodeY(8)) PictureBox10.Location = New Point(NodeX(9), NodeY(9)) PictureBox11.Location = New Point(NodeX(10), NodeY(10)) PictureBox12.Location = New Point(NodeX(11), NodeY(11)) PictureBox13.Location = New Point(NodeX(12), NodeY(12)) PictureBox14.Location = New Point(NodeX(13), NodeY(13)) PictureBox15.Location = New Point(NodeX(14), NodeY(14)) PictureBox16.Location = New Point(NodeX(15), NodeY(15)) PictureBox17.Location = New Point(NodeX(16), NodeY(16)) PictureBox18.Location = New Point(NodeX(17), NodeY(17)) PictureBox19.Location = New Point(NodeX(18), NodeY(18)) PictureBox20.Location = New Point(NodeX(19), NodeY(19)) ' need to add labels as well Label1.Location = New Point(NodeX(0), NodeY(0) + 20) Label2.Location = New Point(NodeX(1), NodeY(1) + 20) Label3.Location = New Point(NodeX(2), NodeY(2) + 20) Label4.Location = New Point(NodeX(3), NodeY(3) + 20) Label5.Location = New Point(NodeX(4), NodeY(4) + 20) Label6.Location = New Point(NodeX(5), NodeY(5) + 20) Label7.Location = New Point(NodeX(6), NodeY(6) + 20) Label8.Location = New Point(NodeX(7), NodeY(7) + 20) Label9.Location = New Point(NodeX(8), NodeY(8) + 20) Label10.Location = New Point(NodeX(9), NodeY(9) + 20) Label11.Location = New Point(NodeX(10), NodeY(10) + 20) Label12.Location = New Point(NodeX(11), NodeY(11) + 20) Label13.Location = New Point(NodeX(12), NodeY(12) + 20) Label14.Location = New Point(NodeX(13), NodeY(13) + 20) Label15.Location = New Point(NodeX(14), NodeY(14) + 20) Label16.Location = New Point(NodeX(15), NodeY(15) + 20) Label17.Location = New Point(NodeX(16), NodeY(16) + 20) Label18.Location = New Point(NodeX(17), NodeY(17) + 20) Label19.Location = New Point(NodeX(18), NodeY(18) + 20) Label20.Location = New Point(NodeX(19), NodeY(19) + 20) For i = 0 To 19 Temperature(i) = 3000 ' start with a middle sort of temp Next RedoColors() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click ' work out distances to other nodes, if < a certain distance then we are friends Dim i, j As Integer Dim x, y, x1, y1 As Integer Dim d As Single Dim DistanceConstant As Integer = 300 ' number of pixels For i = 0 To 19 For j = 0 To 19 x = NodeX(i) y = NodeY(i) x1 = NodeX(j) y1 = NodeY(j) d = ((x1 - x) ^ 2 + (y1 - y) ^ 2) ^ 0.5 ' pythagoras If d > 1 And d < DistanceConstant Then ' 0 is myself Friends(i) += Strings.Chr(j + 65) End If Next Next ' now list in a textbox For i = 0 To 19 TextBox1.Text += Strings.Chr(i + 65) + "=" + Friends(i) + vbCrLf Next Timer1.Enabled = True End Sub 'Given a temperature (in Kelvin), estimate an RGB equivalent 'http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ Private Sub getRGBfromTemperature(ByRef r As Long, ByRef g As Long, ByRef b As Long, ByVal tmpKelvin As Long) Static tmpCalc As Double 'Temperature must fall between 1000 and 40000 degrees If tmpKelvin < 1000 Then tmpKelvin = 1000 If tmpKelvin > 40000 Then tmpKelvin = 40000 'All calculations require tmpKelvin \ 100, so only do the conversion once tmpKelvin = tmpKelvin \ 100 'Calculate each color in turn 'First: red If tmpKelvin <= 66 Then r = 255 Else 'Note: the R-squared value for this approximation is .988 tmpCalc = tmpKelvin - 60 tmpCalc = 329.698727446 * (tmpCalc ^ -0.1332047592) r = tmpCalc If r < 0 Then r = 0 If r > 255 Then r = 255 End If 'Second: green If tmpKelvin <= 66 Then 'Note: the R-squared value for this approximation is .996 tmpCalc = tmpKelvin tmpCalc = 99.4708025861 * Log(tmpCalc) - 161.1195681661 g = tmpCalc If g < 0 Then g = 0 If g > 255 Then g = 255 Else 'Note: the R-squared value for this approximation is .987 tmpCalc = tmpKelvin - 60 tmpCalc = 288.1221695283 * (tmpCalc ^ -0.0755148492) g = tmpCalc If g < 0 Then g = 0 If g > 255 Then g = 255 End If 'Third: blue If tmpKelvin >= 66 Then b = 255 ElseIf tmpKelvin <= 19 Then b = 0 Else 'Note: the R-squared value for this approximation is .998 tmpCalc = tmpKelvin - 10 tmpCalc = 138.5177312231 * Log(tmpCalc) - 305.0447927307 b = tmpCalc If b < 0 Then b = 0 If b > 255 Then b = 255 End If End Sub Private Sub RedoColors() Dim r, g, b As Integer ' redo all the colors getRGBfromTemperature(r, g, b, Temperature(0)) PictureBox1.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(1)) PictureBox2.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(2)) PictureBox3.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(3)) PictureBox4.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(4)) PictureBox5.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(5)) PictureBox6.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(6)) PictureBox7.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(7)) PictureBox8.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(8)) PictureBox9.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(9)) PictureBox10.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(10)) PictureBox11.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(11)) PictureBox12.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(12)) PictureBox13.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(13)) PictureBox14.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(14)) PictureBox15.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(15)) PictureBox16.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(16)) PictureBox17.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(17)) PictureBox18.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(18)) PictureBox19.BackColor = Color.FromArgb(r, g, b) getRGBfromTemperature(r, g, b, Temperature(19)) PictureBox20.BackColor = Color.FromArgb(r, g, b) End Sub Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click SendHeat() End Sub Private Sub SendHeat() ' starts with node A. Send some heat to any nodes that A can contact ' each of these nodes waits a random time, then sends on with some of the heat removed ' each node only sends once and sends its own temp ' so each node needs to record when the heat arrived, how much arrived Dim Joules As Integer Dim Source As Integer ' from this node Dim Hops As Integer Source = 0 ' start node - A=0, B=1 etc, always start with A Joules = 30000 - Temperature(Source) ' as source gets hotter, send out less energy otherwise overflows Hops = 20 ' dies after n hops, optimum seems to be that number of hops roughly equals number of nodes Inbox(Source, 0) = Hops Inbox(Source, 1) = Joules HopString = "Last hop sequence = A" End Sub Sub ProcessMessage() ' each message bounces around until it dies. Each bounce is to a random friend take 20%, send on Dim i, j As Integer Dim Joules As Single Dim Hops As Integer Dim MyJoules As Single Dim Dest As Integer Dim n As Single Dim RemainingJoules As Single Dim MyFriends As Integer For i = 0 To 19 ' check all nodes Hops = Inbox(i, 0) Joules = Inbox(i, 1) If Hops > 0 Then ' message for me, process it, send it to a random friend MyJoules = Joules * 0.1 RemainingJoules = Joules - MyJoules Temperature(i) += MyJoules ' add to my temperature Inbox(i, 0) = 0 Inbox(i, 1) = 0 ' clear my values Hops -= 1 If Hops > 0 Then ' send on to a random friend which includes where it might have just come from MyFriends = Strings.Len(Friends(i)) ' how many friends I have ' send based on a random number. Need to be very careful translating between languages ' does rnd() include zero, and does it include 1 (vb.net, yes and no respectively) ' also caution with trancating vs rounding 1.6 truncated is 1 but rounded is 2 n = Rnd() * MyFriends n += 1 n = Math.Truncate(n) If n < 1 Then n = 1 ' not the best solution but safest to avoid string out of range errors If n > MyFriends Then n = MyFriends n = Convert.ToInt16(n) Dest = Strings.Asc(Strings.Mid(Friends(i), n, 1)) - 65 Inbox(Dest, 0) = Hops ' send on to this random friend Inbox(Dest, 1) = RemainingJoules HopString += Strings.Chr(Dest + 65) Label21.Text = HopString End If End If Next End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick Call LoseHeat() ProcessMessage() RedoColors() DisplayTemps() SendCounter += 1 If SendCounter > 30 Then SendCounter = 0 SendHeat() End If End Sub Sub LoseHeat() Dim i As Integer Dim Ambient As Single = 1000 ' cools down to ambient which is 1000K as this is red on the color chart For i = 0 To 19 Temperature(i) = Temperature(i) - ((Temperature(i) - Ambient) * 0.005) ' cool down a bit each 100ms Next End Sub Sub DisplayTemps() Dim i As Integer TextBox2.Clear() For i = 0 To 19 TextBox2.Text += Strings.Chr(i + 65) + "=" + Convert.ToString(Math.Truncate(Temperature(i))) + vbCrLf Next End Sub Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click Timer1.Enabled = False End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Randomize() End Sub End Class
Comments
What I would LOVE to design something using either the FM or AM tx/rx work others have already done but can't seem to wrap my head around the RF part. I imagine that if you were to set a specific frequency to use (somewhere in the unlicensed bands) it might be possible. Keep in mind I don't plan on using such a device over a very far distance, maybe a few hundred feet? Seems plausible to me, although without a lot of study I'd be very afraid to start playing with this (I live in close proximity to a large airport).
I'm not sure how many people would need functionality that an xbee doesn't have (Digimesh?), although being able to omit the pricey radio and use a few external components to handle the RF while letting the propeller do the rest is very attractive. I could see real promise if a CHEAP transceiver module was used (open-wire) and the propeller was left to handle all the rest (that way the FCC wouldn't have any reason to be knocking at my door).