Skip to content

Commit 30c806e

Browse files
author
Timothy Tamm
authored
Arduino comms (#32)
* init commit: raspberry to arduino communication added * added baud rate and simplified names * added orientationMsg.proto and start with $ * added in functionality to read in from Arduino * fixed missing message * fixed import error * fixed more bugs and added $ check to stringToMessage * fixes * added message * pi-arduino comms and pi-base comms * fixes * navball works * getting output from pi * joystick fixes * testin ploulu servo ctrl * updated comms * maestro y u no work * add controller skeleton
1 parent 3448ac9 commit 30c806e

33 files changed

+339
-57
lines changed

arduinoCommsModule.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import robomodules as rm
5+
import serial
6+
from messages import *
7+
8+
ADDRESS = os.environ.get("BIND_ADDRESS","localhost")
9+
PORT = os.environ.get("BIND_PORT", 11297)
10+
11+
FREQUENCY = 10
12+
13+
class ArduinoCommsModule(rm.ProtoModule):
14+
def __init__(self, addr, port):
15+
self.subscriptions = [MsgType.CTRL_MSG]
16+
super().__init__(addr, port, message_buffers, MsgType, FREQUENCY, self.subscriptions)
17+
try:
18+
self.serialConnection = serial.Serial('/dev/ttyACM0', 9600, timeout=0)
19+
except Exception:
20+
raise RuntimeError("serial connection to Arduino failed")
21+
22+
def msg_received(self, msg, msg_type):
23+
if msg_type == MsgType.CTRL_MSG:
24+
arduino_msg = self._stringToBinary(self._messageToString(msg))
25+
print(arduino_msg)
26+
self.serialConnection.write(arduino_msg)
27+
28+
def tick(self):
29+
line = self.serialConnection.readline()
30+
if len(line) > 0:
31+
msg = self._stringToMessage(self._binaryToString(line))
32+
if msg:
33+
self.write(msg.SerializeToString(), MsgType.ORIENTATION_MSG)
34+
35+
def _messageToString(self, m):
36+
ans = "$"
37+
for prop in ["x", "y", "z", "roll", "pitch", "yaw", "cameraTilt", "cameraPan"]:
38+
ans += (str(getattr(m, prop)) + ";")
39+
ans += "\0"
40+
return ans
41+
42+
def _stringToBinary(self, s):
43+
return bytes(s, "ascii")
44+
45+
def _binaryToString(self, b):
46+
return b.decode('ascii')
47+
48+
def _stringToMessage(self, s):
49+
ans = OrientationMsg()
50+
if s[0] == '$':
51+
s = s[1:]
52+
else:
53+
return None
54+
numbers = (s.split(";"))[0:-1]
55+
if len(numbers) != 3:
56+
return None
57+
# assumes the values are coming in in that order
58+
for (number, name) in zip(numbers, ["roll", "pitch", "yaw"]):
59+
setattr(ans, name, float(number))
60+
return ans
61+
62+
63+
def main():
64+
module = ArduinoCommsModule(ADDRESS, PORT)
65+
module.run()
66+
67+
if __name__ == "__main__":
68+
main()

guiModule.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
PORT = os.environ.get("BIND_PORT", 11297)
1414

1515
FREQUENCY = 25
16-
NAVBALL_FREQ = 1
16+
NAVBALL_FREQ = 5
1717
FRAME_WIDTH = 640
1818
SCREEN_SIZE = (FRAME_WIDTH*3, 900)
1919
NAVBALL_SIZE = 300
2020

2121
class GuiModule(rm.ProtoModule):
2222
def __init__(self, addr, port):
23-
self.subscriptions = [MsgType.CAMERA_FRAME_MSG, MsgType.CTRL_MSG, MsgType.HUMIDITY_MSG]
23+
self.subscriptions = [MsgType.CAMERA_FRAME_MSG, MsgType.CTRL_MSG, MsgType.HUMIDITY_MSG, MsgType.ORIENTATION_MSG]
2424
super().__init__(addr, port, message_buffers, MsgType, FREQUENCY, self.subscriptions)
2525
self.frames = {}
2626
pygame.init()
@@ -41,11 +41,13 @@ def msg_received(self, msg, msg_type):
4141
if msg_type == MsgType.CAMERA_FRAME_MSG:
4242
self.frames[msg.id] = msg.cameraFrame
4343
elif msg_type == MsgType.CTRL_MSG:
44-
self.roll = msg.roll * 90
45-
self.pitch = msg.pitch * 90
46-
self.yaw = msg.yaw * 90
44+
return
4745
elif msg_type == MsgType.HUMIDITY_MSG:
4846
self.humidity = msg.humidity
47+
elif msg_type == MsgType.ORIENTATION_MSG:
48+
self.roll = msg.roll
49+
self.yaw = msg.yaw + 180
50+
self.pitch = msg.pitch + 180
4951

5052
def tick(self):
5153
for event in pygame.event.get():

ino/client/client.ino

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
#include <Wire.h>
2+
#include <Servo.h>
3+
#include <Adafruit_Sensor.h>
4+
#include <Adafruit_BNO055.h>
5+
#include <utility/imumaths.h>
6+
7+
#define TICKS_PER_WRITE 200
8+
9+
#define PANSERVO 2
10+
#define TILTSERVO 3
11+
#define T1 4
12+
#define T2 5
13+
#define T3 6
14+
#define T4 7
15+
#define T5 8
16+
#define T6 9
17+
18+
#define FRONT_LEFT 0
19+
#define FRONT_RIGHT 1
20+
#define BACK_LEFT 2
21+
#define BACK_RIGHT 3
22+
#define SIDE_LEFT 4
23+
#define SIDE_RIGHT 5
24+
25+
#define THRUSTER_BASE 1500
26+
#define THRUSTER_MAX 400
27+
28+
struct message {
29+
float x;
30+
float y;
31+
float z;
32+
float roll;
33+
float pitch;
34+
float yaw;
35+
float cameraTilt;
36+
float cameraPan;
37+
};
38+
39+
Adafruit_BNO055 bno = Adafruit_BNO055(55);
40+
int ticks = 0;
41+
42+
Servo panServo;
43+
Servo tiltServo;
44+
45+
Servo thrusters[6];
46+
47+
int panPos = 90;
48+
int tiltPos = 90;
49+
50+
struct message curMsg;
51+
52+
void setup(void)
53+
{
54+
Serial.begin(9600);
55+
56+
// Initialise the IMU
57+
if(!bno.begin()) {
58+
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
59+
while(1);
60+
}
61+
62+
// initialize servos
63+
panServo.attach(PANSERVO);
64+
tiltServo.attach(TILTSERVO);
65+
66+
// initialize thrusters
67+
thrusters[0].attach(T1);
68+
thrusters[1].attach(T2);
69+
thrusters[2].attach(T3);
70+
thrusters[3].attach(T4);
71+
thrusters[4].attach(T5);
72+
thrusters[5].attach(T6);
73+
74+
thrusters[0].writeMicroseconds(1500);
75+
thrusters[1].writeMicroseconds(1500);
76+
thrusters[2].writeMicroseconds(1500);
77+
thrusters[3].writeMicroseconds(1500);
78+
thrusters[4].writeMicroseconds(1500);
79+
thrusters[5].writeMicroseconds(1500);
80+
81+
delay(1000);
82+
83+
bno.setExtCrystalUse(true);
84+
}
85+
86+
void print_orientation(sensors_event_t event) {
87+
Serial.print('$');
88+
Serial.print(event.orientation.x);
89+
Serial.print(';');
90+
Serial.print(event.orientation.y);
91+
Serial.print(';');
92+
Serial.print(event.orientation.z);
93+
Serial.print(';');
94+
Serial.print('\n');
95+
}
96+
97+
int read_message(struct message *msg) {
98+
if (Serial.available() == 0) {
99+
return 0;
100+
}
101+
int field = 0;
102+
int inChr;
103+
String inString = "";
104+
// Find start
105+
while(true) {
106+
inChr = Serial.read();
107+
if ((char)inChr == '$') {
108+
break;
109+
}
110+
if(Serial.available() == 0) {
111+
return 0;
112+
}
113+
}
114+
115+
while (field < 8) {
116+
while(Serial.available() == 0);
117+
inChr = Serial.read();
118+
if ((char)inChr == ';') {
119+
inString += '\0';
120+
switch(field) {
121+
case 0:
122+
msg->x = inString.toFloat();
123+
break;
124+
case 1:
125+
msg->y = inString.toFloat();
126+
break;
127+
case 2:
128+
msg->z = inString.toFloat();
129+
break;
130+
case 3:
131+
msg->roll = inString.toFloat();
132+
break;
133+
case 4:
134+
msg->pitch = inString.toFloat();
135+
break;
136+
case 5:
137+
msg->yaw = inString.toFloat();
138+
break;
139+
case 6:
140+
msg->cameraTilt = inString.toFloat();
141+
break;
142+
case 7:
143+
msg->cameraPan = inString.toFloat();
144+
break;
145+
}
146+
field++;
147+
inString = "";
148+
} else {
149+
inString += (char) inChr;
150+
}
151+
}
152+
return 1;
153+
}
154+
155+
void simpleController(struct message *msg) {
156+
// TODO: ADD controller
157+
}
158+
159+
void loop(void)
160+
{
161+
// get sensor event
162+
sensors_event_t event;
163+
bno.getEvent(&event);
164+
165+
// TODO: run PID
166+
167+
/* Sample: Turn all thrusters on. value has to be in between 1100 and 1900
168+
thrusters[0].writeMicroseconds(1700);
169+
thrusters[1].writeMicroseconds(1700);
170+
thrusters[2].writeMicroseconds(1700);
171+
thrusters[3].writeMicroseconds(1700);
172+
thrusters[4].writeMicroseconds(1700);
173+
thrusters[5].writeMicroseconds(1700); */
174+
175+
if (ticks % TICKS_PER_WRITE == 0) {
176+
//print_orientation(event);
177+
}
178+
// read from Serial
179+
if (read_message(&curMsg)) {
180+
if (curMsg.cameraTilt > 0) {
181+
tiltPos+= 10;
182+
} else if (curMsg.cameraTilt < 0) {
183+
tiltPos-= 10;
184+
}
185+
if (tiltPos > 360) {
186+
tiltPos = 360;
187+
} else if (tiltPos < -180) {
188+
tiltPos = -180;
189+
}
190+
191+
if (curMsg.cameraPan > 0) {
192+
panPos+= 10;
193+
} else if (curMsg.cameraPan < 0) {
194+
panPos-= 10;
195+
}
196+
if (panPos > 360) {
197+
panPos = 360;
198+
} else if (panPos < -180) {
199+
panPos = -180;
200+
}
201+
202+
}
203+
Serial.print(panPos);
204+
Serial.print(" ");
205+
Serial.println(tiltPos);
206+
panServo.writeMicroseconds(1100 + panPos*5);
207+
//tiltServo.write(tiltPos);
208+
delay(500);
209+
ticks++;
210+
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

ino/sensor/sensor.ino

-47
This file was deleted.

joystickModule.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
ADDRESS = os.environ.get("BIND_ADDRESS","localhost")
1010
PORT = os.environ.get("BIND_PORT", 11297)
1111

12-
FREQUENCY = 20
12+
FREQUENCY = 5
1313

1414
class JoystickModule(rm.ProtoModule):
1515
def __init__(self, addr, port):
@@ -20,6 +20,8 @@ def __init__(self, addr, port):
2020
self.pitch = 0.
2121
self.yaw = 0.
2222
self.roll = 0.
23+
self.camera_tilt = 0.
24+
self.camera_pan = 0.
2325
self.logitech = None
2426
pygame.init()
2527
pygame.joystick.init()
@@ -57,6 +59,8 @@ def tick(self):
5759
msg.pitch = self.pitch
5860
msg.yaw = self.yaw
5961
msg.roll = self.roll
62+
msg.cameraTilt = self.camera_tilt
63+
msg.cameraPan = self.camera_pan
6064
msg = msg.SerializeToString()
6165
self.write(msg, MsgType.CTRL_MSG)
6266

@@ -72,6 +76,10 @@ def _get_input(self):
7276
buttonRB = joy.get_button(5)
7377
buttonLT = joy.get_button(6)
7478
buttonRT = joy.get_button(7)
79+
tpl = joy.get_hat(0)
80+
81+
self.camera_tilt = tpl[0]
82+
self.camera_pan = tpl[1]
7583

7684
# -1 <= up < 0 < down <= +1
7785
if buttonLB:

0 commit comments

Comments
 (0)