bzr branch
http://bzr.ed.am/elec/quadcopter
19
by Tim Marston
added python GTK test program that reads and displays the serial data from the |
1 |
#!/usr/bin/python |
2 |
# |
|
3 |
# rc-interface-test |
|
4 |
||
5 |
||
6 |
import pygtk |
|
7 |
pygtk.require( '2.0' ); |
|
8 |
import gtk, serial, struct |
|
9 |
from io import BytesIO |
|
10 |
||
11 |
||
12 |
class MainDialogue: |
|
13 |
||
14 |
||
15 |
# number of channels to read |
|
16 |
NUM_CHANNELS = 8 |
|
17 |
||
18 |
# maximum channel value |
|
19 |
MAX_CHANNEL_VALUE = 1000 |
|
20 |
||
21 |
# serial device to use |
|
22 |
SERIAL_DEVICE = '/dev/ttyACM0' |
|
23 |
||
24 |
||
25 |
def __init__( self ): |
|
26 |
self.link = serial.Serial( self.SERIAL_DEVICE, 9600 ) |
|
27 |
self.got_one = False |
|
28 |
self.channel_values = [] |
|
29 |
self.quit = False |
|
30 |
self.buffer = bytearray() |
|
31 |
||
32 |
||
33 |
def setup_window( self ): |
|
34 |
||
35 |
# create and set up window |
|
36 |
self.window = gtk.Window( gtk.WINDOW_TOPLEVEL ) |
|
37 |
self.window.connect( "delete_event", self.destroy ) |
|
38 |
self.window.connect( "destroy", self.destroy ) |
|
39 |
self.window.set_title( "Testing rc-interface serial comms" ); |
|
40 |
self.window.set_border_width( 30 ) |
|
41 |
self.window.set_modal( True ) |
|
42 |
self.window.connect( "key-press-event", self.key_press_event ) |
|
43 |
||
44 |
# add widgets |
|
45 |
table = gtk.Table( self.NUM_CHANNELS, 2 ) |
|
46 |
table.set_row_spacings( 20 ) |
|
47 |
table.set_col_spacings( 10 ) |
|
48 |
self.window.add( table ) |
|
49 |
||
50 |
# add channels |
|
51 |
self.controls = [] |
|
52 |
for a in range( 0, self.NUM_CHANNELS ): |
|
53 |
||
54 |
label = gtk.Label( "Channel %d" % ( a + 1 ) ) |
|
55 |
table.attach( label, 0, 1, a, a + 1 ) |
|
56 |
||
57 |
adj = gtk.Adjustment( 0, 0, self.MAX_CHANNEL_VALUE, 1, 0, 0 ) |
|
58 |
control = gtk.HScale( adj ) |
|
59 |
control.set_draw_value( False ) |
|
60 |
control.set_property( 'width-request', 300 ) |
|
61 |
control.set_sensitive( False ) |
|
62 |
table.attach( control, 1, 2, a, a + 1 ) |
|
63 |
||
64 |
self.controls.append( control ) |
|
65 |
||
66 |
# show it |
|
67 |
self.window.show_all() |
|
68 |
||
69 |
||
70 |
def key_press_event( self, widget, event ): |
|
71 |
if event.keyval == gtk.keysyms.Escape: |
|
72 |
self.window.destroy() |
|
73 |
else: |
|
74 |
return False |
|
75 |
||
76 |
||
77 |
def destroy( self, widget, data = None ): |
|
78 |
self.quit = True |
|
79 |
||
80 |
||
81 |
def process_serial_data_at( self, pos ): |
|
82 |
for a in range( 0, self.NUM_CHANNELS ): |
|
83 |
at = 2 * a + pos |
|
84 |
value = struct.unpack( "h", self.buffer[ at : at + 2 ] )[ 0 ] |
|
85 |
||
86 |
# update control |
|
87 |
self.controls[ a ].set_value( value ) |
|
88 |
||
89 |
||
90 |
def read_serial( self ): |
|
91 |
||
92 |
# try and read |
|
93 |
in_waiting = self.link.inWaiting() |
|
94 |
if( in_waiting ): |
|
95 |
self.buffer.extend( self.link.read( in_waiting ) ) |
|
96 |
||
97 |
# check buffer for double -1 |
|
98 |
got = bytearray() |
|
99 |
i = 0 |
|
100 |
while i < len( self.buffer ): |
|
101 |
||
102 |
# check foir double -1 |
|
103 |
if i > 0 and self.buffer[ i ] == 255 and \ |
|
104 |
self.buffer[ i - 1 ] == 255: |
|
105 |
||
106 |
# if we've got enough data, process it |
|
107 |
start_index = i - ( self.NUM_CHANNELS * 2 + 1 ) |
|
108 |
if start_index >= 0: |
|
109 |
self.process_serial_data_at( start_index ) |
|
110 |
||
111 |
# remove everything up to and including this double -1 from |
|
112 |
# the serial buffer |
|
113 |
self.buffer = self.buffer[ i + 1 : ] |
|
114 |
i = 0 |
|
115 |
||
116 |
else: |
|
117 |
i += 1 |
|
118 |
||
119 |
||
120 |
def main( self ): |
|
121 |
self.setup_window() |
|
122 |
while not self.quit: |
|
123 |
||
124 |
# update gtk |
|
125 |
while gtk.events_pending(): |
|
126 |
gtk.main_iteration( False ) |
|
127 |
||
128 |
# check serial interface |
|
129 |
self.read_serial() |
|
130 |
||
131 |
||
132 |
MainDialogue().main() |