РЕДАКТИРОВАТЬ: ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ:
Поскольку окончательное решение было скрыто в комментариях, я выложу его здесь для будущих зрителей.
Моя проблема в том, что сигнал, который я использовал для остановки действия, включал «r», а также команду для остановки (я думал, что я был умным, комбинируя мою «левую» команду и команду «стоп»). Код C ++ (arduino) считывает каждый символ индивидуально, следовательно, останавливает сигнал в целом, а не только тот, который я хотел.
Спасибо тебе dbasnett за то, что выкладываем это 🙂
Хорошо, привет, это мой последний вопрос для моего последнего проекта. Идея была в том, чтобы создать программу для управления автомобилем через Arduino. Оно работает!!! (только с небольшой ошибкой).
Просто я использую клавиши со стрелками или WASD для управления программой. Он посылает сигнал через последовательный порт на Arduino, который имеет несколько функций для интерпретации сигнала. Всего у вас есть 9 сигналов, которые можно отправить; по одному для каждого направления, по одному для остановки каждого входного направления (например, при левом направлении колеса автомобиля направляются влево, при остановке влево колеса направляются прямо вперед).
ПРОБЛЕМА: Когда я иду вперед (или назад) и Влево (или вправо), если я изменяю НАПРАВЛЕНИЕ (влево / вправо), все останавливается вместе. Я потратил большую часть проекта, пытаясь решить эту проблему, и я просто не вижу, что я делаю неправильно.
Итак, мой код:
Imports System.IO.Ports
Imports System.IO
Imports System.Threading
Public Class Form1
Shared _continue As Boolean
Shared _serialPort As SerialPort
Shared lturn As Boolean
Shared rturn As Boolean
Shared keydelay As Integer = 0
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
SerialPort1.PortName = "com3" 'change com port to match your Arduino port
SerialPort1.BaudRate = 115200
SerialPort1.DataBits = 8
SerialPort1.Parity = Parity.None
SerialPort1.StopBits = StopBits.One
SerialPort1.Handshake = Handshake.None
SerialPort1.Encoding = System.Text.Encoding.Default 'very important!
End Sub
Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
Dim bHandled As Boolean = False
If SerialPort1.IsOpen Then
Else
SerialPort1.Open()
End If
Select Case e.KeyCode
Case Keys.Right
pbBgML.BackColor = Color.Transparent
pbBgMR.BackColor = Color.Black
SerialPort1.Write("d")
e.Handled = True
Case Keys.Left
pbBgMR.BackColor = Color.Transparent
pbBgML.BackColor = Color.Black
SerialPort1.Write("a")
e.Handled = True
Case Keys.Up
pbBgBC.BackColor = Color.Transparent
pbBgTC.BackColor = Color.Black
SerialPort1.Write("w")
e.Handled = True
Case Keys.Down
pbBgTC.BackColor = Color.Transparent
pbBgBC.BackColor = Color.Black
SerialPort1.Write("s")
e.Handled = True
Case Keys.Space
SerialPort1.Write("r")
e.Handled = True
End Select
End Sub
Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As KeyEventArgs) Handles Me.KeyUp
Select Case e.KeyCode
Case Keys.Right
pbBgMR.BackColor = Color.Transparent
SerialPort1.Write("dr")
Case Keys.Left
pbBgML.BackColor = Color.Transparent
SerialPort1.Write("ar")
Case Keys.Up
pbBgTC.BackColor = Color.Transparent
SerialPort1.Write("wr")
Case Keys.Down
pbBgBC.BackColor = Color.Transparent
SerialPort1.Write("sr")
End Select
End Sub
End Class
Кроме того, если вы хотите, код Arduino (в C ++):
// Car Control v. 0.2
int reversePin = 9;
int forwardPin = 8;
int leftPin = 10;
int rightPin = 11;
byte byteRead;
int time;
void forward(int time){
digitalWrite(reversePin, HIGH);
Serial.println("This is forward...");
digitalWrite(forwardPin, LOW);
delay(time);
}
void reverse(int time){
digitalWrite(forwardPin, HIGH);
Serial.println("This is reverse...");
digitalWrite(reversePin, LOW);
delay(time);
}
void left(int time){
digitalWrite(rightPin, HIGH);
Serial.println("This is left...");
digitalWrite(leftPin, LOW);
delay(time);
}
void right(int time){
digitalWrite(leftPin, HIGH);
Serial.println("This is right...");
digitalWrite(rightPin, LOW);
delay(time);
}
void off(){
Serial.println("This is stop...");
digitalWrite(leftPin, HIGH);
digitalWrite(rightPin, HIGH);
digitalWrite(reversePin, HIGH);
digitalWrite(forwardPin, HIGH);
}
void setup() {
// initialize the digital pins as an output.
pinMode(rightPin, OUTPUT);
pinMode(leftPin, OUTPUT);
pinMode(forwardPin, OUTPUT);
pinMode(reversePin, OUTPUT);
Serial.begin(115200);
Serial.print("\n\nStart...\n");
}
void loop()
{
//Turn everything off...
if (Serial.available()) {
/* read the most recent byte */
byteRead = Serial.read();
switch(byteRead)
{
case 'w':
forward(5);
break;
case 'wr':
digitalWrite(forwardPin, HIGH);
break;
case 's':
reverse(5);
break;
case 'sr':
digitalWrite(reversePin, HIGH);
break;
case 'a':
left(5);
break;
case 'ar':
digitalWrite(leftPin, HIGH);
break;
case 'd':
right(5);
break;
case 'dr':
digitalWrite(rightPin, HIGH);
break;
case 'r':
off();
break;
}
}
}
Извините за огромные блоки текста, но я просто понятия не имею, где проблема. Ура ребята.
Я не могу помочь с кодом C, но код VB может использовать один байт для контроля
<FlagsAttribute()> _
Enum ctrl As Byte
stp = 0 'stop is no bits set
frwd = 1 << 0 '1
back = 1 << 1 '2
left = 1 << 2 '4
rght = 1 << 3 '8
mask = 255
End Enum
Private _control(0) As ctrl
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.Right
_control(0) = _control(0) Or ctrl.rght
Case Keys.Left
_control(0) = _control(0) Or ctrl.left
Case Keys.Up
_control(0) = _control(0) Or ctrl.frwd
Case Keys.Down
_control(0) = _control(0) Or ctrl.back
End Select
'SerialPort1.Write(_control, 0, 1)
Debug.WriteLine(_control(0))
End Sub
Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
Select Case e.KeyCode
Case Keys.Right
_control(0) = _control(0) And (ctrl.mask Xor ctrl.rght)
Case Keys.Left
_control(0) = _control(0) And (ctrl.mask Xor ctrl.left)
Case Keys.Up
_control(0) = _control(0) And (ctrl.mask Xor ctrl.frwd)
Case Keys.Down
_control(0) = _control(0) And (ctrl.mask Xor ctrl.back)
End Select
'SerialPort1.Write(_control, 0, 1)
Debug.WriteLine(_control(0))
End Sub
Я думаю, что ваш подход немного не здесь.
Я бы посоветовал вам использовать битовое поле, чтобы определить, какой вход нажимается с разным битом для каждого входа (так как каждый фактически независим).
Private _input As Integer = 0
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
'set the bit of the required input
Select Case e.KeyCode
Case Keys.Right
_input = SetBit(_input, 0) '0001
Case Keys.Left
_input = SetBit(_input, 1) '0010
Case Keys.Up
_input = SetBit(_input, 2) '0100
Case Keys.Down
_input = SetBit(_input, 3) '1000
End Select
SerialPort1.Write(Convert.ToChar(_input))
End Sub
Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
'clear the bit of the de-selected input
Select Case e.KeyCode
Case Keys.Right
_input = ClearBit(_input, 0)
Case Keys.Left
_input = ClearBit(_input, 1)
Case Keys.Up
_input = ClearBit(_input, 2)
Case Keys.Down
_input = ClearBit(_input, 3)
End Select
SerialPort1.Write(Convert.ToChar(_input))
End Sub
Private Function SetBit(value As Integer, bit As Integer) As Integer
' Create a bitmask with the 2 to the nth power bit set:
Dim mask As Integer = CInt(2 ^ bit)
' Set the nth Bit:
value = value Or mask
Return value
End Function
Private Function ClearBit(value As Integer, bit As Integer) As Integer
' Create a bitmask with the 2 to the nth power bit set:
Dim mask As Integer = CInt(2 ^ bit)
' Clear the nth Bit:
value = value And Not mask
Return value
End Function
Затем вам нужно сделать обратное в коде C ++ (который должен быть намного более элегантным) и проверить наличие недопустимых комбинаций клавиш (например, вперед и назад вместе).
В идеале вы хотели бы передать байт на последовательный порт без символа, но я постарался сделать его максимально похожим