| Wheelchair Control Diploma Thesis, Author: Ondrej Vozda, FEEC BUT, 2013

- Main Page
- Packages
- Classes
- Files

- File List

All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
FormRegulators.cs
1 ﻿using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.IO.Ports;
10
11 namespace WheelchairControl
12 {
16 public partial class FormRegulators : Form
17 {
18 #region Delegates
19
24 public delegate void UARTSend_Delegate(uint[] data);
25
31 public delegate void toolStripLogClickDelegate(object sender, EventArgs e);
32
33 #endregion
34
35 #region Constants
36
40 private const Byte STOP_REQUEST_REPEATS = 3;
41
45 private const Byte RX_DATA_LENGTH = FormMain.RX_DATA_LENGTH;
46
50 private const Byte ANGLE_REGULATOR_INCREMENT = 1;
51
55 private enum ComboBoxAngleUnit : byte
56 {
60 DEGREES,
61
65 MILIRADIANS,
66
67 ITEMS_COUNT
68 };
69
70 #endregion
71
72 #region Private variables
73
77 private static FormRegulators instance = null;
78
82 private static Object singeltonLock = new Object();
83
87 private SerialPort serialPort_formMain;
88
92 private ToolStripMenuItem formMainLogToolStrip;
93
97 private UARTSend_Delegate UARTSendMethod;
98
102 private toolStripLogClickDelegate toolStripLogClickMethod;
103
104 #endregion
105
106 #region Private methods
107
112 private void SendStopSequence()
113 {
114 UInt32[] outputBuffer = new UInt32[RX_DATA_LENGTH - 1];
115
116 for (Byte i = 0; i < STOP_REQUEST_REPEATS; i++) //Send mutiple times, just for sure
117 {
118 outputBuffer[0] = 0xC4; //Stop request for both motors
119 outputBuffer[1] = 128;
120 outputBuffer[2] = 128;
121 UARTSendMethod(outputBuffer);
122 }
123 }
124
128 private void ResetOdometry()
129 {
130 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
131
132 outputBuffer[0] = 0xA3;
133 outputBuffer[1] = 0x00;
134 outputBuffer[2] = 0x00;
135 UARTSendMethod(outputBuffer);
136 }
137
138 #endregion
139
147 private FormRegulators(SerialPort formMainCOMPort, UARTSend_Delegate SendMethod, toolStripLogClickDelegate LogClickDelegate, ToolStripMenuItem toolStripLog)
148 {
149 serialPort_formMain = formMainCOMPort;
150 UARTSendMethod = SendMethod;
151 toolStripLogClickMethod = LogClickDelegate;
152 formMainLogToolStrip = toolStripLog;
153
154 //Register handler
155 FormMain.COMStatusChanged += delegate()
156 {
157 if (this.InvokeRequired)
158 {
159 this.Invoke((MethodInvoker)delegate
160 {
161 FormRegulators_Activated(this, null);
162 });
163 }
164 else
165 {
166 FormRegulators_Activated(this, null);
167 }
168 };
169
170 InitializeComponent();
171 }
172
181 public static FormRegulators GetInstance(SerialPort formMainCOMPort, UARTSend_Delegate sendMethod, toolStripLogClickDelegate logClickDelegate, ToolStripMenuItem toolStripLog)
182 {
183 //Prevent possible thread race
184 lock (singeltonLock)
185 {
186 if (instance == null || instance.IsDisposed) //Create new singleton instance
187 instance = new FormRegulators(formMainCOMPort, sendMethod, logClickDelegate, toolStripLog);
188 }
189
190 return instance;
191 }
192
193 private void buttonSTOP_Click(object sender, EventArgs e)
194 {
195 SendStopSequence();
196
197 tsslInfo.Text = "STOP signal has been sent.";
198
199 //Stop log
200 if (formMainLogToolStrip.Text == "Stop log")
201 toolStripLogClickMethod(sender, null);
202 }
203
204 private void FormRegulators_Activated(object sender, EventArgs e)
205 {
206 UInt16 FORM_TO_BUTTONSTOP_HEIGH_RATIO = 61;
207
208 //Com port status info & controls enable
209 if (serialPort_formMain.IsOpen)
210 {
211 tssLabelComPortState.Text = "COM Port Status: OPEN";
212
213 //Enable buttons
214 foreach (Control controlItem in this.Controls)
215 controlItem.Enabled = true;
216 }
217 else
218 {
219 tssLabelComPortState.Text = "COM Port Status: CLOSED";
220 tsslInfo.Text = "Port closed, controls are disabled!";
221
222 //Disable buttons (leave status strip enabled)
223 foreach (Control controlItem in this.Controls)
224 if (controlItem.GetType() != typeof(StatusStrip))
225 controlItem.Enabled = false;
226 }
227
228 //Resize form
229 buttonSTOP.Height = (collapsibleGroupBoxSettings.Top + collapsibleGroupBoxSettings.Height) - buttonSTOP.Top;
230 this.Height = buttonSTOP.Height + FORM_TO_BUTTONSTOP_HEIGH_RATIO;
231 }
232
233 private void buttonStartWallFollowing_Click(object sender, EventArgs e)
234 {
235 //Confirm start
236 if (checkBoxStartConfirmation.Checked &&
237 MessageBox.Show("Start the wall following?", "Confirmation required!", MessageBoxButtons.YesNo,
238 MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != DialogResult.Yes)
239 {
240 return;
241 }
242
243 //Declare variables
244 UInt16 tempY;
245 Int32 tempV;
246 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
247
248 //Reset odometry
249 if (checkBoxResetOdometry.Checked)
250 ResetOdometry();
251
252 //Set focus on stop button to allow easier emergency stop
253 buttonSTOP.Focus();
254
255 //Convert parameters
256 try
257 {
258 tempV = Convert.ToInt32(textBoxVdes.Text) + 128;
259 tempY = Convert.ToUInt16(textBoxY0Des.Text);
260 }
261 catch (Exception ex)
262 {
263 if (ex is OverflowException || ex is FormatException)
264 {
265 //Process wrong parameter exceptions
266 tsslInfo.Text = "Wrong parameter specified!";
267
268 return;
269 }
270 else
271 //Other exceptions are thrown higher
272 throw;
273 }
274
275 if (tempY < 0 || tempY > 255 || tempV < 0 || tempV > 255) //Address out of range
276 {
277 MessageBox.Show("Only distances 0 - 255 & speeds -128 - 127 allowed!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
278 }
279 else
280 {
281 outputBuffer[0] = 0xC6;
282 outputBuffer[1] = (Byte)(tempV);
283 outputBuffer[2] = (Byte)tempY;
284 UARTSendMethod(outputBuffer);
285 }
286
287 //Start log if no logging is active
288 if (formMainLogToolStrip.Text != "Stop log" && checkBoxEnableLog.Checked)
289 toolStripLogClickMethod(sender, null);
290
291 tsslInfo.Text = "Wall following started!";
292 }
293
294 private void buttonPositionRegulator_Click(object sender, EventArgs e)
295 {
296 //Confirm start
297 if (checkBoxStartConfirmation.Checked &&
298 MessageBox.Show("Start the position regulator?", "Confirmation required!", MessageBoxButtons.YesNo,
299 MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != DialogResult.Yes)
300 {
301 return;
302 }
303
304 //Declare variables
305 Int16 tempX;
306 Int16 tempY;
307 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
308
309 //Reset odometry
310 if (checkBoxResetOdometry.Checked)
311 ResetOdometry();
312
313 //Set focus on stop button to allow easier emergency stop
314 buttonSTOP.Focus();
315
316 //Convert parameters
317 try
318 {
319 tempX = Convert.ToInt16(textBoxXdes.Text);
320 tempY = Convert.ToInt16(textBoxYdes.Text);
321 }
322 catch (Exception ex)
323 {
324 if (ex is OverflowException || ex is FormatException)
325 {
326 //Process wrong parameter exceptions
327 tsslInfo.Text = "Wrong parameter specified!";
328
329 return;
330 }
331 else
332 //Other exceptions are thrown higher
333 throw;
334 }
335
336 //Send desired X position
337 outputBuffer[0] = 0xD0;
338 outputBuffer[1] = (Byte)(tempX >> 8);
339 outputBuffer[2] = (Byte)(tempX & 0x00FF);
340 UARTSendMethod(outputBuffer);
341
342 //Send desired Y position
343 outputBuffer[0] = 0xD1;
344 outputBuffer[1] = (Byte)(tempY >> 8);
345 outputBuffer[2] = (Byte)(tempY & 0x00FF);
346 UARTSendMethod(outputBuffer);
347
348 //Start position regulator
349 outputBuffer[0] = 0xC7;
350 outputBuffer[1] = 0x00;
351 outputBuffer[2] = 0x00;
352 UARTSendMethod(outputBuffer);
353
354 //Start log if no logging is active
355 if (formMainLogToolStrip.Text != "Stop log" && checkBoxEnableLog.Checked)
356 toolStripLogClickMethod(sender, null);
357
358 tsslInfo.Text = "Position regulation started!";
359 }
360
361 private void buttonRegulateAngle_Click(object sender, EventArgs e)
362 {
363 //Confirm start
364 if (checkBoxStartConfirmation.Checked &&
365 MessageBox.Show("Start the angle regulator?", "Confirmation required!", MessageBoxButtons.YesNo,
366 MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != DialogResult.Yes)
367 {
368 return;
369 }
370
371 //Declare variables
372 UInt16 angle;
373 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
374
375 //Reset odometry
376 if (checkBoxResetOdometry.Checked)
377 ResetOdometry();
378
379 //Set focus on stop button to allow easier emergency stop
380 buttonSTOP.Focus();
381
382 //Convert parameters
383 try
384 {
385 switch (comboBoxAngleUnits.SelectedIndex)
386 {
387 case (Int32)ComboBoxAngleUnit.MILIRADIANS:
388
389 //Normalize to 0 - 2PI (miliradians)
390 angle = (UInt16)(1000.0 * ((Convert.ToDouble(textBoxAngle.Text) / 1000.0) % (2 * Math.PI)));
391
392 break;
393
394 case (Int32)ComboBoxAngleUnit.DEGREES:
395
396 //Convert and normalize to 0 - 2PI (miliradians)
397 angle = (UInt16)(1000.0 * ((Convert.ToDouble(textBoxAngle.Text) * (Math.PI / 180.0)) % (2 * Math.PI)));
398
399 break;
400
401 default:
402 return; //Error
403 }
404 }
405 catch (Exception ex)
406 {
407 if (ex is OverflowException || ex is FormatException)
408 {
409 //Process wrong parameter exceptions
410 tsslInfo.Text = "Wrong parameter specified!";
411
412 return;
413 }
414 else
415 //Other exceptions are thrown higher
416 throw;
417 }
418
419 //0 would disable angle regulator, send small value instead
420 if (angle == 0)
421 angle = ANGLE_REGULATOR_INCREMENT;
422
423 //Start angle regulator
424 outputBuffer[0] = 0xC7;
425 outputBuffer[1] = (Byte)(angle >> 8);
426 outputBuffer[2] = (Byte)(angle & 0x00FF);
427 UARTSendMethod(outputBuffer);
428
429 //Start log if no logging is active
430 if (formMainLogToolStrip.Text != "Stop log" && checkBoxEnableLog.Checked)
431 toolStripLogClickMethod(sender, null);
432
433 tsslInfo.Text = "Angle regulation started! Angle increment: " + angle.ToString() + " mrad";
434 }
435
436 private void FormRegulators_FormClosing(object sender, FormClosingEventArgs e)
437 {
438 //Save settings
439 WheelchairControl.Properties.Settings.Default.Setting_CheckboxLogToFileEnabled = checkBoxEnableLog.Checked;
440 WheelchairControl.Properties.Settings.Default.Setting_CheckboxRequireStartConfirmation = checkBoxStartConfirmation.Checked;
441 WheelchairControl.Properties.Settings.Default.Setting_CheckboxResetOdometry = checkBoxResetOdometry.Checked;
442
443 WheelchairControl.Properties.Settings.Default.Save();
444 }
445
446 private void FormRegulators_Load(object sender, EventArgs e)
447 {
448 //Restore settings
449 checkBoxEnableLog.Checked = WheelchairControl.Properties.Settings.Default.Setting_CheckboxLogToFileEnabled;
450 checkBoxStartConfirmation.Checked = WheelchairControl.Properties.Settings.Default.Setting_CheckboxRequireStartConfirmation;
451 checkBoxResetOdometry.Checked = WheelchairControl.Properties.Settings.Default.Setting_CheckboxResetOdometry;
452
453 //Select degrees in combobox
454 comboBoxAngleUnits.SelectedIndex = (Int32)ComboBoxAngleUnit.DEGREES;
455
456 //Select last waypoint
457 comboBoxWaypointSelection.SelectedIndex = comboBoxWaypointSelection.Items.Count - 1;
458 }
459
460 private void collapsibleGroupBoxSettings_CollapseBoxClickedEvent(object sender)
461 {
462 UInt16 FORM_TO_BUTTONSTOP_HEIGH_RATIO = 61;
463
464 //Resize form
465 buttonSTOP.Height = (collapsibleGroupBoxSettings.Top + collapsibleGroupBoxSettings.Height) - buttonSTOP.Top;
466 this.Height = buttonSTOP.Height + FORM_TO_BUTTONSTOP_HEIGH_RATIO;
467 }
468
469 private void buttonOdometryResetAll_Click(object sender, EventArgs e)
470 {
471 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1] { 0xA3, 0x00, 0x00 };
472
473 //Stop motors -> position regulator could start the wheelchair if odometry is reset
474 SendStopSequence();
475
476 UARTSendMethod(outputBuffer);
477
478 tsslInfo.Text = "All coordinates reset";
479 }
480
481 private void buttonOdometrySetPhi_Click(object sender, EventArgs e)
482 {
483 Int16 tempValue;
484 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
485
486 //Stop motors -> position regulator could start the wheelchair if odometry is reset
487 SendStopSequence();
488
489 //Convert parameters
490 try
491 {
492 tempValue = Convert.ToInt16(textBoxOdometryPhi.Text);
493 }
494 catch (Exception ex)
495 {
496 if (ex is OverflowException || ex is FormatException)
497 {
498 //Process wrong parameter exceptions
499 tsslInfo.Text = "Wrong parameter specified!";
500
501 return;
502 }
503 else
504 //Other exceptions are thrown higher
505 throw;
506 }
507
508 outputBuffer[0] = 0xA2;
509 outputBuffer[1] = (Byte)(tempValue >> 8);
510 outputBuffer[2] = (Byte)(tempValue & 0x00FF);
511 UARTSendMethod(outputBuffer);
512
513 tsslInfo.Text = "Odometry Phi set to " + tempValue.ToString() + ".";
514 }
515
516 private void buttonOdometrySetY_Click(object sender, EventArgs e)
517 {
518 Int16 tempValue;
519 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
520
521 //Stop motors -> position regulator could start the wheelchair if odometry is reset
522 SendStopSequence();
523
524 //Convert parameters
525 try
526 {
527 tempValue = Convert.ToInt16(textBoxOdometryY.Text);
528 }
529 catch (Exception ex)
530 {
531 if (ex is OverflowException || ex is FormatException)
532 {
533 //Process wrong parameter exceptions
534 tsslInfo.Text = "Wrong parameter specified!";
535
536 return;
537 }
538 else
539 //Other exceptions are thrown higher
540 throw;
541 }
542
543 outputBuffer[0] = 0xA1;
544 outputBuffer[1] = (Byte)(tempValue >> 8);
545 outputBuffer[2] = (Byte)(tempValue & 0x00FF);
546 UARTSendMethod(outputBuffer);
547
548 tsslInfo.Text = "Odometry Y set to " + tempValue.ToString() + ".";
549 }
550
551 private void buttonOdometrySetX_Click(object sender, EventArgs e)
552 {
553 Int16 tempValue;
554 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
555
556 //Stop motors -> position regulator could start the wheelchair if odometry is reset
557 SendStopSequence();
558
559 //Convert parameters
560 try
561 {
562 tempValue = Convert.ToInt16(textBoxOdometryX.Text);
563 }
564 catch (Exception ex)
565 {
566 if (ex is OverflowException || ex is FormatException)
567 {
568 //Process wrong parameter exceptions
569 tsslInfo.Text = "Wrong parameter specified!";
570
571 return;
572 }
573 else
574 //Other exceptions are thrown higher
575 throw;
576 }
577
578 outputBuffer[0] = 0xA0;
579 outputBuffer[1] = (Byte)(tempValue >> 8);
580 outputBuffer[2] = (Byte)(tempValue & 0x00FF);
581 UARTSendMethod(outputBuffer);
582
583 tsslInfo.Text = "Odometry X set to " + tempValue.ToString() + ".";
584 }
585
586 private void buttonTestFinalApproach_Click(object sender, EventArgs e)
587 {
588 //No more implemented on this form, test function on FormMain
589 tsslInfo.Text = "Function unavailable on this form. Use FormMain instead.";
590 }
591
592 private void buttoFollowPathFromWaypoint_Click(object sender, EventArgs e)
593 {
594 //No more implemented on this form, test function on FormMain
595 tsslInfo.Text = "Function unavailable on this form. Use FormMain instead.";
596 }
597
598 private void buttonFindMarks_Click(object sender, EventArgs e)
599 {
600 //No more implemented on this form, test function on FormMain
601 tsslInfo.Text = "Function unavailable on this form. Use FormMain instead.";
602 }
603
604 private void buttonTestBackwardDrive_Click(object sender, EventArgs e)
605 {
606 //No more implemented on this form, test function on FormMain
607 tsslInfo.Text = "Function unavailable on this form. Use FormMain instead.";
608 }
609
610 private void buttonSetXdes_Click(object sender, EventArgs e)
611 {
612 Int16 tempX = 0;
613 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
614
615 //Convert parameters
616 try
617 {
618 tempX = Convert.ToInt16(textBoxXdes.Text);
619 }
620 catch (Exception ex)
621 {
622 if (ex is OverflowException || ex is FormatException)
623 {
624 //Process wrong parameter exceptions
625 tsslInfo.Text = "Wrong parameter specified!";
626
627 return;
628 }
629 else
630 //Other exceptions are thrown higher
631 throw;
632 }
633
634 //Send desired X position
635 outputBuffer[0] = 0xD0;
636 outputBuffer[1] = (Byte)(tempX >> 8);
637 outputBuffer[2] = (Byte)(tempX & 0x00FF);
638 UARTSendMethod(outputBuffer);
639
640 //Info
641 tsslInfo.Text = "Desired X coordinate set to: " + tempX.ToString() + " cm.";
642 }
643
644 private void buttonSetYdes_Click(object sender, EventArgs e)
645 {
646 Int16 tempY = 0;
647 uint[] outputBuffer = new uint[RX_DATA_LENGTH - 1];
648
649 //Convert parameters
650 try
651 {
652 tempY = Convert.ToInt16(textBoxYdes.Text);
653 }
654 catch (Exception ex)
655 {
656 if (ex is OverflowException || ex is FormatException)
657 {
658 //Process wrong parameter exceptions
659 tsslInfo.Text = "Wrong parameter specified!";
660
661 return;
662 }
663 else
664 //Other exceptions are thrown higher
665 throw;
666 }
667
668 //Send desired Y position
669 outputBuffer[0] = 0xD1;
670 outputBuffer[1] = (Byte)(tempY >> 8);
671 outputBuffer[2] = (Byte)(tempY & 0x00FF);
672 UARTSendMethod(outputBuffer);
673
674 //Info
675 tsslInfo.Text = "Desired Y coordinate set to: " + tempY.ToString() + " cm.";
676 }
677 }
678 }