Simply3DScan
ArduinoCommands.cs
Go to the documentation of this file.
1 using System;
2 using System.IO.Ports;
3 using System.Threading;
4 using System.Threading.Tasks;
5 using Logging;
6 using SharedObjects;
7 
9 {
13  public class ArduinoCommands
14  {
15 
16  private readonly int baudRate;
17  private SerialPort currentPort;
18 
25  public bool PortFound { get; private set; }
26 
33  public string PortString { get; private set; }
34 
40  [Log]
41  [LogException]
42  public ArduinoCommands(int baudRate, string portString = "")
43  {
44  Singleton<Logger>.Instance.LogInfo($"Starting arduino connection with baudrate:{baudRate}");
45 
46  this.baudRate = baudRate;
47  if (String.IsNullOrEmpty(portString))
48  this.FindComPort();
49  else
50  {
51  this.PortString = portString;
52  this.currentPort = new SerialPort(this.PortString, baudRate) {ReadTimeout = 2000};
53  }
54 
55  if (null != this.currentPort)
56  this.currentPort.ErrorReceived += this.CurrentPortOnErrorReceived;
57 
58  }
59 
60  [Log]
61  [LogException]
62  private void CurrentPortOnErrorReceived(object sender, SerialErrorReceivedEventArgs serialErrorReceivedEventArgs)
63  {
64  if (null != this.currentPort)
65  {
66  this.currentPort.ErrorReceived -= this.CurrentPortOnErrorReceived;
67  this.currentPort.Dispose();
68  this.currentPort = null;
69  }
70 
71  this.currentPort = new SerialPort(this.PortString, this.baudRate) { ReadTimeout = 2000 };
72 
73  if (null != this.currentPort)
74  this.currentPort.ErrorReceived += this.CurrentPortOnErrorReceived;
75  }
76 
82  [Log]
83  public string FindComPort()
84  {
85  try
86  {
87  string[] ports = SerialPort.GetPortNames();
88  foreach (string port in ports)
89  {
90  string testPort = port;
91  Task<string> detectPort = Task<string>.Factory.StartNew(() =>
92  {
93  Singleton<Logger>.Instance.LogInfo($"Testing COM port:{testPort}");
94  SerialPort serialPort = new SerialPort(testPort, this.baudRate) {ReadTimeout = 2000};
95  return this.DetectArduino(serialPort) ? testPort : String.Empty;
96  });
97 
98  if (detectPort.Wait(5000))
99  {
100 
101  string detectedPort = detectPort.Result;
102 
103  if (String.IsNullOrEmpty(detectedPort))
104  this.PortFound = false;
105  else
106  {
107  Singleton<Logger>.Instance.LogInfo($"Using Arduino on COM port:{detectedPort}");
108  this.PortString = detectedPort;
109  this.PortFound = true;
110  this.currentPort = new SerialPort(testPort, this.baudRate) {ReadTimeout = 2000};
111  return this.PortString;
112  }
113  }
114  else
115  {
116  this.PortFound = false;
117  }
118  }
119  }
120  catch (Exception ex)
121  {
122  Singleton<Logger>.Instance.LogException(ex);
123  }
124  return string.Empty;
125  }
126 
131  [Log]
132  public void ActivateLaser(bool on = true)
133  {
134  this.SendCommand(@on
137  }
138 
144  [Log]
145  public void ActivateLight(bool on, int hue)
146  {
147  if (on)
148  this.SendCommand(CommandRepresentations.EnableLightCommand, hue);
149  else
151  }
152 
157  [Log]
158  public void RotateTurnTableCw(int steps)
159  {
160  this.SendCommand(CommandRepresentations.RotateTurnTableCwCommand, steps);
161  }
162 
167  [Log]
168  public void RotateTurnTableCcw(int steps)
169  {
170  this.SendCommand(CommandRepresentations.RotateTurnTableCcwCommand, steps);
171  }
172 
177  [Log]
178  public void RotateLaserCw(int steps)
179  {
180  this.SendCommand(CommandRepresentations.RotateLaserCwCommand, steps);
181  }
182 
187  [Log]
188  public void RotateLaserCcw(int steps)
189  {
190  this.SendCommand(CommandRepresentations.RotateLaserCcwCommand, steps);
191  }
192 
196  [Log]
197  public void EnableMicroStepping()
198  {
200  }
201 
205  [Log]
206  public void DisableMicroStepping()
207  {
209  }
210 
219  [Log]
220  [LogException]
221  private bool DetectArduino(SerialPort serialPort)
222  {
223  try
224  {
225  //The below setting are for the Hello handshake
226  byte[] buffer = new byte[1];
227  buffer[0] = Convert.ToByte(CommandRepresentations.Ping);
228 
229  Singleton<Logger>.Instance.LogInfo($"Try open port {serialPort}");
230  serialPort.Open();
231 
232  Singleton<Logger>.Instance.LogInfo($"Ask for reply on port {serialPort}");
233  serialPort.Write(buffer, 0, 1);
234  try
235  {
236  Singleton<Logger>.Instance.LogInfo($"Wait for result on port {serialPort}");
237  int intReturnAscii = serialPort.ReadByte();
238  Singleton<Logger>.Instance.LogInfo($"Detected on port {serialPort}");
239  return intReturnAscii == CommandRepresentations.ACK;
240  }
241  catch (TimeoutException)
242  {
243  Singleton<Logger>.Instance.LogInfo($"Not detected on port {serialPort}");
244  return false;
245  }
246  }
247  catch (Exception ex)
248  {
249  Singleton<Logger>.Instance.LogInfo($"Not detected on port {serialPort}");
250  Singleton<Logger>.Instance.LogException(ex);
251  }
252  finally
253  {
254  Singleton<Logger>.Instance.LogInfo($"Close port {serialPort}");
255  if(serialPort.IsOpen)
256  serialPort.Close();
257  }
258 
259  return false;
260  }
261 
272  [LogException]
273  private bool SendCommand(int command, int parameter = -1, int retry = 5)
274  {
275  try
276  {
277  byte[] buffer = parameter == -1 ? new byte[1] : new byte[2];
278 
279  buffer[0] = Convert.ToByte(command);
280  if (parameter != -1)
281  buffer[1] = Convert.ToByte(parameter);
282  this.currentPort.Open();
283  this.currentPort.Write(buffer, 0, parameter == -1 ? 1 : 2);
284 
285  return this.currentPort.ReadByte() == CommandRepresentations.ACK;
286  }
287  catch (TimeoutException)
288  {
289  Singleton<Logger>.Instance.LogWarning($"Command took longer then expected: {command}");
290  return false;
291  }
292  catch (UnauthorizedAccessException uax)
293  {
294  // happens if port is not ready.
295  if (retry <= 0)
296  {
297  Singleton<Logger>.Instance.LogException(uax);
298  return false;
299  }
300 
301  Thread.Sleep(20);
302  return this.SendCommand(command, parameter, retry - 1);
303 
304  }
305  catch (Exception ex)
306  {
307  Singleton<Logger>.Instance.LogException(ex);
308  return false;
309  }
310  finally
311  {
312  if (this.currentPort.IsOpen)
313  this.currentPort.Close();
314  }
315  }
316  }
317 }
const int RotateTurnTableCcwCommand
The rotate turn table counter clockwise command
void ActivateLight(bool on, int hue)
Activates the light.
const int DisableLightCommand
The disable light command
Class for detecting an arduino and sending commands to it
void RotateLaserCw(int steps)
Rotates the laser clockwise.
const int RotateLaserCwCommand
The rotate laser clockwise command
const int DisableMicroSteppingCommand
The disable micro stepping command
void DisableMicroStepping()
Disables the micro stepping.
const int RotateTurnTableCwCommand
The rotate turn table clockwise command
Class for creating a singleton for a generic class
Definition: Singleton.cs:9
const int EnableMicroSteppingCommand
The enable micro stepping command
void EnableMicroStepping()
Enables the micro stepping.
const int RotateLaserCcwCommand
The rotate laser counterclockwise command
Representations of commands and states to control arduino sketch
const int DisableLaserCommand
The disable laser command
Definition: Logger.cs:5
const int EnableLaserCommand
The enable laser command
void RotateTurnTableCcw(int steps)
Rotates the turn table counter clockwise.
void RotateTurnTableCw(int steps)
Rotates the turn table clockwise.
string PortString
Gets the port string.
static T Instance
Gets the instance.
Definition: Singleton.cs:27
void ActivateLaser(bool on=true)
Activates the laser.
ArduinoCommands(int baudRate, string portString="")
Initializes a new instance of the ArduinoCommands class.
void RotateLaserCcw(int steps)
Rotates the laser counter clockwise.
const int EnableLightCommand
The enable light command
string FindComPort()
Finds the COM port used by arduino
bool PortFound
Gets a value indicating whether [port found].