Commit d9d096654b60a4186c37e26a4aa4cd8e350f3d61
1 parent
ba381288
Exists in
master
Demo reading two values from serial, plotting them on the same graph
Showing
4 changed files
with
43 additions
and
26 deletions
Show diff stats
robots/little_john/telemetry/code/monitor/version1/main.py
@@ -40,7 +40,7 @@ else: | @@ -40,7 +40,7 @@ else: | ||
40 | os='Other' | 40 | os='Other' |
41 | logging.info('OS = ' + os) | 41 | logging.info('OS = ' + os) |
42 | 42 | ||
43 | -testseries = Series(points=150, ylimits=(9, 1024), title="Sine wave demo", xname="Time (s)", yname="100sin(t)") | 43 | +testseries = Series(points=150, ylimits=(0, 1024), title="Data from serial", xname="Time (s)", yname="ADC output") |
44 | plots = [] | 44 | plots = [] |
45 | plots.append(Plot(testseries)) | 45 | plots.append(Plot(testseries)) |
46 | 46 | ||
@@ -48,13 +48,22 @@ def pollSerial(elapsed): | @@ -48,13 +48,22 @@ def pollSerial(elapsed): | ||
48 | """Check serial port for incoming data""" | 48 | """Check serial port for incoming data""" |
49 | # Note: 'elapsed' is time since last call of this function | 49 | # Note: 'elapsed' is time since last call of this function |
50 | # This works, but it might be better for performance to have two seperate functions, only one of which is run. | 50 | # This works, but it might be better for performance to have two seperate functions, only one of which is run. |
51 | - if os=='Windows': | ||
52 | - values = datafeed.readline().strip().split(b", ") | ||
53 | - else: | ||
54 | - values = datafeed.readline().strip() | ||
55 | - values = values.split(b', ') | 51 | + try: |
52 | + if os=='Windows': | ||
53 | + values = datafeed.readline().strip().split(b", ") | ||
54 | + else: | ||
55 | + values = datafeed.readline().strip() | ||
56 | + values = values.split(b', ') | ||
57 | + except: | ||
58 | + logging.error("Failed to recieve or parse input data") | ||
59 | + return | ||
60 | + | ||
56 | for n, value in enumerate(values): | 61 | for n, value in enumerate(values): |
57 | - values[n] = float(value) | 62 | + try: |
63 | + values[n] = float(value) | ||
64 | + except: | ||
65 | + logging.error("Failed to convert input to float") | ||
66 | + return | ||
58 | #logging.info("Recieved data: " + str(values)) | 67 | #logging.info("Recieved data: " + str(values)) |
59 | testseries.addpoint([time.time()-starttime] + values) | 68 | testseries.addpoint([time.time()-starttime] + values) |
60 | 69 | ||
@@ -66,6 +75,6 @@ def fakePollSerial(elapsed): | @@ -66,6 +75,6 @@ def fakePollSerial(elapsed): | ||
66 | testseries.addpoint(values) | 75 | testseries.addpoint(values) |
67 | 76 | ||
68 | # Pyglet looks after the main event loop, but this ensures that data keeps being read in | 77 | # Pyglet looks after the main event loop, but this ensures that data keeps being read in |
69 | -pyglet.clock.schedule_interval(pollSerial, 0.04) | 78 | +pyglet.clock.schedule_interval(pollSerial, 0.01) |
70 | 79 | ||
71 | pyglet.app.run() | 80 | pyglet.app.run() |
robots/little_john/telemetry/code/monitor/version1/plot.py
@@ -40,7 +40,7 @@ class Plot(pyglet.window.Window): | @@ -40,7 +40,7 @@ class Plot(pyglet.window.Window): | ||
40 | self.drawHeading() | 40 | self.drawHeading() |
41 | self.drawAxis(0) | 41 | self.drawAxis(0) |
42 | self.drawAxis(1) | 42 | self.drawAxis(1) |
43 | - self.drawLine(self.series) | 43 | + self.drawLines(self.series) |
44 | 44 | ||
45 | def drawBackground(self): | 45 | def drawBackground(self): |
46 | """Draw the graph background, currently a plain colour""" | 46 | """Draw the graph background, currently a plain colour""" |
@@ -54,7 +54,7 @@ class Plot(pyglet.window.Window): | @@ -54,7 +54,7 @@ class Plot(pyglet.window.Window): | ||
54 | anchor_x='center', anchor_y='top') | 54 | anchor_x='center', anchor_y='top') |
55 | heading.draw() | 55 | heading.draw() |
56 | 56 | ||
57 | - def drawLine(self, series): | 57 | + def drawLines(self, series): |
58 | xscale = float(self.series.xlimits[1]-self.series.xlimits[0])/(self.bounds[0][1]-self.bounds[0][0]) | 58 | xscale = float(self.series.xlimits[1]-self.series.xlimits[0])/(self.bounds[0][1]-self.bounds[0][0]) |
59 | yscale = float(self.series.ylimits[1]-self.series.ylimits[0])/(self.bounds[1][1]-self.bounds[1][0]) | 59 | yscale = float(self.series.ylimits[1]-self.series.ylimits[0])/(self.bounds[1][1]-self.bounds[1][0]) |
60 | lmar = int(self.width * self.margins[0]) | 60 | lmar = int(self.width * self.margins[0]) |
@@ -63,17 +63,24 @@ class Plot(pyglet.window.Window): | @@ -63,17 +63,24 @@ class Plot(pyglet.window.Window): | ||
63 | bmar = int(self.height * self.margins[1]) | 63 | bmar = int(self.height * self.margins[1]) |
64 | 64 | ||
65 | pyglet.gl.glLineWidth(2) | 65 | pyglet.gl.glLineWidth(2) |
66 | - | ||
67 | - for n in range(len(series.data) - 1): | ||
68 | - x1, y1 = series.data[n][0]-series.xlimits[0], series.data[n][1]-series.ylimits[0] | ||
69 | - x2, y2 = series.data[n+1][0]-series.xlimits[0], series.data[n+1][1]-series.ylimits[0] | ||
70 | - x1 = int((x1/xscale)+lmar) | ||
71 | - y1 = int((y1/yscale)+bmar) | ||
72 | - x2 = int((x2/xscale)+lmar) | ||
73 | - y2 = int((y2/yscale)+bmar) | ||
74 | - pyglet.graphics.draw(2, pyglet.gl.GL_LINES, | ||
75 | - ('v2i', (x1, y1, x2, y2)), | ||
76 | - ('c3B', (255, 0, 0, 255, 0, 0))) | 66 | + |
67 | + linecolours = [(255, 0, 0, 255, 0, 0), (0, 0, 255, 0, 0, 255)] | ||
68 | + | ||
69 | + try: | ||
70 | + for m in range(len(series.data[0])-1): | ||
71 | + for n in range(len(series.data) - 1): | ||
72 | + x1, y1 = series.data[n][0]-series.xlimits[0], series.data[n][m+1]-series.ylimits[0] | ||
73 | + x2, y2 = series.data[n+1][0]-series.xlimits[0], series.data[n+1][m+1]-series.ylimits[0] | ||
74 | + x1 = int((x1/xscale)+lmar) | ||
75 | + y1 = int((y1/yscale)+bmar) | ||
76 | + x2 = int((x2/xscale)+lmar) | ||
77 | + y2 = int((y2/yscale)+bmar) | ||
78 | + pyglet.graphics.draw(2, pyglet.gl.GL_LINES, | ||
79 | + ('v2i', (x1, y1, x2, y2)), | ||
80 | + ('c3B', linecolours[m])) | ||
81 | + except: | ||
82 | + logging.error("Failed to plot lines, possibly due to corrupt/missing data. (This happens at startup)") | ||
83 | + | ||
77 | pyglet.gl.glLineWidth(1) | 84 | pyglet.gl.glLineWidth(1) |
78 | 85 | ||
79 | 86 |
robots/little_john/telemetry/code/monitor/version1/series.py
@@ -32,8 +32,11 @@ class Series: | @@ -32,8 +32,11 @@ class Series: | ||
32 | self.data.append(point) | 32 | self.data.append(point) |
33 | if len(self.data) > self.points: | 33 | if len(self.data) > self.points: |
34 | del self.data[0] | 34 | del self.data[0] |
35 | - self.autoscale(0) | ||
36 | - | 35 | + try: |
36 | + self.autoscale(0) | ||
37 | + except: | ||
38 | + logging.error("Series autoscale failed") | ||
39 | + | ||
37 | def autoscale(self, axis): # axis=0 is x, 1 is y | 40 | def autoscale(self, axis): # axis=0 is x, 1 is y |
38 | minval = self.data[0][axis] | 41 | minval = self.data[0][axis] |
39 | maxval = self.data[0][axis] | 42 | maxval = self.data[0][axis] |
robots/little_john/telemetry/code/robot/analogread_demo/analogread_demo.ino
@@ -6,7 +6,6 @@ | @@ -6,7 +6,6 @@ | ||
6 | * This code is under the GPL | 6 | * This code is under the GPL |
7 | */ | 7 | */ |
8 | 8 | ||
9 | -#include <math.h> | ||
10 | #include <SoftwareSerial.h> | 9 | #include <SoftwareSerial.h> |
11 | 10 | ||
12 | SoftwareSerial Bluetooth(3, 2); // Rx, Tx | 11 | SoftwareSerial Bluetooth(3, 2); // Rx, Tx |
@@ -14,7 +13,6 @@ SoftwareSerial Bluetooth(3, 2); // Rx, Tx | @@ -14,7 +13,6 @@ SoftwareSerial Bluetooth(3, 2); // Rx, Tx | ||
14 | void setup() { | 13 | void setup() { |
15 | Serial.begin(9600); | 14 | Serial.begin(9600); |
16 | Bluetooth.begin(115200); | 15 | Bluetooth.begin(115200); |
17 | - //Bluetooth.print("Hello, wireless world!"); | ||
18 | pinMode(13, OUTPUT); | 16 | pinMode(13, OUTPUT); |
19 | } | 17 | } |
20 | 18 | ||
@@ -25,5 +23,5 @@ void loop() { | @@ -25,5 +23,5 @@ void loop() { | ||
25 | Bluetooth.print(a0value); | 23 | Bluetooth.print(a0value); |
26 | Bluetooth.print(", "); | 24 | Bluetooth.print(", "); |
27 | Bluetooth.println(a7value); | 25 | Bluetooth.println(a7value); |
28 | - delay(500); | 26 | + delay(100); |
29 | } | 27 | } |