Plane | Adding an LCD to the controller, and using Visual Basic for feedback

So pretty easy but important step here. For a while I’ve known that I need to have some more feedback from the robot that just LED brightness levels on the controller. This VB program allows me to get analog values from the vehicle and interpret them in any number of ways. You can download and run that program HERE, and like I said in the video I’ve refrained from going open source with my VB programs in the past because they’ve never really had any polish to them. But now I think it will be good to keep this all open.

I also added a 16 * 2 character LCD to my controller. I’ve sacrificed the 6 pins because hopefully in the long run it will be a better experience for the user. I may go back, but for now I’d rather build around something that’s a little more constraining as it will force me to innovate a little bit more. Here’s a picture of the new controller:

Here’s the program:

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

//Serial Handshake declaration

#include <string.h> // we'll need this for subString

#define MAX_STRING_LEN 100 // like 3 lines above, change as needed.

constcharEOPmarker='.';//This is the end of packet marker

charserialbuf[100];//This gives the incoming serial some room. Change it if you want a longer incoming.

//SoftwareSerial declaration

#include <SoftwareSerial.h>

SoftwareSerial xbee_serial(2,3);

//Shift Register Pins declaration

intSER_Pin=5;//pin 14 on the 75HC595

intRCLK_Pin=6;//pin 12 on the 75HC595

intSRCLK_Pin=7;//pin 11 on the 75HC595

#define number_of_74hc595s 1 //How many of the shift registers - change this

#define numOfRegisterPins number_of_74hc595s * 8 //do not touch

booleanregisters[numOfRegisterPins];

//Servo declarations

intleft_servo_val;

intrght_servo_val;

//lcd declaration

#include <LiquidCrystal.h>

LiquidCrystal lcd(7,8,9,10,11,12);

//Misc Pin declaration

//inputs

intdebug_switch1=4;

intdebug_switch2=6;

//these values are for communication, not hardware inputs

intin_ref;

intin_brightness;

intin_pot1;

intin_pot2;

intin_accelerometer_x;

intin_accelerometer_y;

intin_accelerometer_z;

intin_temp1;

//outputs

//int pot_LED = 6;

intfade_LED=5;

intdebug_switch1_LED=13;

//these values are for communication, not hardware outputs

intout_joystick_x;

intout_joystick_y;

//Misc Integer Declarations

intbrightness=0;// how bright the LED is

intfadeAmount=51;// how many points to fade the LED by

intaccel_x_min=293;

intaccel_x_max=440;

intaccel_y_min=290;

intaccel_y_max=434;

voidsetup(){

Serial.begin(9600);

xbee_serial.begin(9600);

//shift register setup

pinMode(SER_Pin,OUTPUT);

pinMode(RCLK_Pin,OUTPUT);

pinMode(SRCLK_Pin,OUTPUT);

pinMode(0,INPUT);

clearRegisters();

writeRegisters();

//Misc Pin Declarations

pinMode(debug_switch1,INPUT);

pinMode(debug_switch2,INPUT);

//pinMode(pot_LED, OUTPUT);

pinMode(fade_LED,OUTPUT);

//lcd declaration

lcd.begin(16,2);

xbee_serial.print("0,0,0.");// this is very important as it starts of the loop because it makes "xbee_serial.avalible() > 0.

I didn’t mention in in the video, but I moved the mux from the controller, to the vehicle. It allows me to have 22 analog inputs, and the reason I took so long to finally add it was primarily laziness on my part. Aside from the the code is still very similar but close followers will notice that I cleaned up the way the program receives and sends code. It is much much more organized, and much more expandable. Here’s the “new” controller:

Here’s the new program:

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

//Serial Handshake declaration

#include <string.h> // we'll need this for subString

#define MAX_STRING_LEN 100 // like 3 lines above, change as needed.

constcharEOPmarker='.';//This is the end of packet marker

charserialbuf[100];//This gives the incoming serial some room. Change it if you want a longer incoming.

//SoftwareSerial declaration

#include <SoftwareSerial.h>

SoftwareSerial xbee_serial(8,9);

//Mux control pins declarations

ints0=2;

ints1=3;

ints2=4;

ints3=7;

intSIG_pin=0;

//Shift Register Pins declaration

intSER_Pin=10;//pin 14 on the 75HC595

intRCLK_Pin=11;//pin 12 on the 75HC595

intSRCLK_Pin=12;//pin 11 on the 75HC595

#define number_of_74hc595s 1 //How many of the shift registers - change this

#define numOfRegisterPins number_of_74hc595s * 8 //do not touch

booleanregisters[numOfRegisterPins];

//Servo declarations

#include <Servo.h>

Servo left_servo;

Servo rght_servo;

//Misc Pin declaration

//inputs

intdebug_switch1=4;

//outputs

//these values are for communication, not hardware outputs

intout_ref;

intout_pot1;

intout_pot2;

intout_accelerometer_x;

intout_accelerometer_y;

intout_accelerometer_z;

intout_temp1;

intfade_LED=13;

intx_LED=5;

inty_LED=6;

//int debug_switch1_LED = 12;

//Misc Integer declarations

intin_brightness;

intin_joystick_x;

intin_joystick_y;

intbrightness=0;// how bright the LED is

intfadeAmount=51;// how many points to fade the LED by

intx_upperTrigger=600;

intx_lowerTrigger=450;

inty_upperTrigger=600;

inty_lowerTrigger=400;

voidsetup(){

Serial.begin(9600);

xbee_serial.begin(9600);

//mux setup

pinMode(s0,OUTPUT);

pinMode(s1,OUTPUT);

pinMode(s2,OUTPUT);

pinMode(s3,OUTPUT);

digitalWrite(s0,LOW);

digitalWrite(s1,LOW);

digitalWrite(s2,LOW);

digitalWrite(s3,LOW);

//shift register setup

pinMode(SER_Pin,OUTPUT);

pinMode(RCLK_Pin,OUTPUT);

pinMode(SRCLK_Pin,OUTPUT);

clearRegisters();

writeRegisters();

//misc pin declarations

pinMode(x_LED,OUTPUT);

pinMode(y_LED,OUTPUT);

pinMode(fade_LED,OUTPUT);

xbee_serial.print("0,0,0.");// this is very important as it starts of the loop because it makes "xbee_serial.avalible() > 0.

}

voidloop(){

if(xbee_serial.available()>0){

staticintbufpos=0;

charinchar=xbee_serial.read();

if(inchar!=EOPmarker){

serialbuf[bufpos]=inchar;

bufpos++;

}

else{

serialbuf[bufpos]=0;//restart the buff

bufpos=0;//restart the position of the buff

handshake();

setRegisterPin(1,HIGH);

writeRegisters();

}

}

}

voidhandshake(){

//inputs

in_brightness=atoi(subStr(serialbuf,",",1));

in_joystick_x=atoi(subStr(serialbuf,",",2));

in_joystick_y=atoi(subStr(serialbuf,",",3));

analogWrite(fade_LED,in_brightness);

if(in_joystick_x>x_upperTrigger){//the below boolean blocks set pins high or low

setRegisterPin(4,HIGH);

setRegisterPin(5,LOW);

analogWrite(x_LED,map(in_joystick_x,x_upperTrigger,1023,0,255));

writeRegisters();

}

if(in_joystick_x<x_lowerTrigger){

setRegisterPin(4,LOW);

setRegisterPin(5,HIGH);

analogWrite(x_LED,map(in_joystick_x,x_upperTrigger,0,0,255));

writeRegisters();

}

if(in_joystick_x>x_lowerTrigger&&in_joystick_x<x_upperTrigger){

setRegisterPin(4,LOW);

setRegisterPin(5,LOW);

analogWrite(x_LED,0);

writeRegisters();

}

// x above y below

if(in_joystick_y>y_upperTrigger){

setRegisterPin(2,HIGH);

setRegisterPin(3,LOW);

analogWrite(y_LED,map(in_joystick_y,y_upperTrigger,1023,0,255));

writeRegisters();

}

if(in_joystick_y<y_lowerTrigger){

setRegisterPin(2,LOW);

setRegisterPin(3,HIGH);

analogWrite(y_LED,map(in_joystick_y,y_upperTrigger,0,0,255));

writeRegisters();

}

if(in_joystick_y>y_lowerTrigger&&in_joystick_y<y_upperTrigger){

setRegisterPin(2,LOW);

setRegisterPin(3,LOW);

analogWrite(y_LED,0);

writeRegisters();

}

//outputs

brightness=brightness+fadeAmount;

// reverse the direction of the fading at the ends of the fade:

if(brightness==0||brightness==255){

fadeAmount=-fadeAmount;

}

out_ref=readMux(15);

out_pot1=readMux(0);

out_pot2=readMux(1);

out_accelerometer_x=readMux(2);

out_accelerometer_y=readMux(3);

out_accelerometer_z=readMux(4);

out_temp1=readMux(5);

xbee_serial.print(out_ref);

xbee_serial.print(",");

xbee_serial.print(brightness);

xbee_serial.print(",");

xbee_serial.print(out_pot1);

xbee_serial.print(",");

xbee_serial.print(out_pot2);

xbee_serial.print(",");

xbee_serial.print(out_accelerometer_x);

xbee_serial.print(",");

xbee_serial.print(out_accelerometer_y);

xbee_serial.print(",");

xbee_serial.print(out_accelerometer_z);

xbee_serial.print(",");

xbee_serial.print(out_temp1);

xbee_serial.print(".");//EOP marker

delay(10);

}

// for substring

char*subStr(char*input_string,char*separator,intsegment_number){

char*act,*sub,*ptr;

staticcharcopy[MAX_STRING_LEN];

inti;

strcpy(copy,input_string);

for(i=1,act=copy;i<=segment_number;i++,act=NULL){

sub=strtok_r(act,separator,&ptr);

if(sub==NULL)break;

}

returnsub;

}

// for mux

intreadMux(intchannel){

intcontrolPin[]={s0,s1,s2,s3};

intmuxChannel[16][4]={

{0,0,0,0},//channel 0

{1,0,0,0},//channel 1

{0,1,0,0},//channel 2

{1,1,0,0},//channel 3

{0,0,1,0},//channel 4

{1,0,1,0},//channel 5

{0,1,1,0},//channel 6

{1,1,1,0},//channel 7

{0,0,0,1},//channel 8

{1,0,0,1},//channel 9

{0,1,0,1},//channel 10

{1,1,0,1},//channel 11

{0,0,1,1},//channel 12

{1,0,1,1},//channel 13

{0,1,1,1},//channel 14

{1,1,1,1}//channel 15

};

//loop through the 4 sig

for(inti=0;i<4;i++){

digitalWrite(controlPin[i],muxChannel[channel][i]);

}

//read the value at the SIG pin

intval=analogRead(SIG_pin);

//return the value

returnval;

}

// for shift registers

voidclearRegisters(){

for(inti=numOfRegisterPins-1;i>=0;i--){

registers[i]=LOW;

}

}

// for shift registers

voidwriteRegisters(){

digitalWrite(RCLK_Pin,LOW);

for(inti=numOfRegisterPins-1;i>=0;i--){

digitalWrite(SRCLK_Pin,LOW);

intval=registers[i];

digitalWrite(SER_Pin,val);

digitalWrite(SRCLK_Pin,HIGH);

}

digitalWrite(RCLK_Pin,HIGH);

}

//set an individual pin HIGH or LOW

voidsetRegisterPin(intindex,intvalue){

registers[index]=value;

}

Like I promised in the video, here are a few more properly focused pictures:

Hey! This post was written a long time ago, but I'm leaving it up on the off-chance it may help someone, but proceed with caution. It may not be a good idea to blindly integrate this code or work into your project, but instead use it as a starting point.