dim22
March 27, 2016, 9:39pm
1
Hi,
I try to control four servomotors by usin c# winforms
To drive one no problem:
arduino code
#include <Servo.h>
Servo articulationa;
int val=0;
void setup() {
Serial.begin(9600);
articulationa.attach(3);
}
void loop() {
}
void serialEvent() {
val=Serial.parseInt();
articulationa.write(val);
}
The c# code ( on the form there is two butons (connecté) (déconnecté) to connect the port, one checkbox to select the trackbar and one trackbar)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace commandearticulaire
{
public partial class Form1 : Form
{
SerialPort port = new SerialPort();
public string data;
public Form1()
{
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e) { }
private void trackBar1_Scroll(object sender, EventArgs e)
{
if (port.IsOpen & checkBox1.Checked)
{
port.WriteLine(trackBar1.Value.ToString());
valarti2.Text = "angleepaule2=" + trackBar1.Value.ToString(); } }
private void Form3_FormClosing(object sender, FormClosingEventArgs e)
{ {
if (port.IsOpen) port.Close();
} }
private void Form1_Load(object sender, EventArgs e)
{ }
private void connecté_Click(object sender, EventArgs e)
{ port.PortName = "COM4";
port.BaudRate = 9600;
port.Open();
if (port.IsOpen)
{
connecté.Enabled = false;
déconnecté.Enabled = true; } }
private void déconnecté_Click(object sender, EventArgs e)
{
port.Close();
if (!port.IsOpen)
{ connecté.Enabled = true;
déconnecté.Enabled = false; } }
private void checkBox1_Click(object sender, EventArgs e)
{ }
}
now i would like to control severals servomotors (two at begining)
but i don't know how select them
if someone has an idea it will be great
system
March 27, 2016, 9:43pm
2
private void label1_Click(object sender, EventArgs e) { }
Why have you registered a callback for clicking on a label?
private void Form3_FormClosing(object sender, FormClosingEventArgs e)
{ {
if (port.IsOpen) port.Close();
} }
Get a clue as to where curly braces are needed and where they look stupid.
but i don't know how select them
Use random() to just randomly pick one. If YOU don't know which one the data is for, how the hell can we know?
dim22
March 28, 2016, 5:39am
3
Ok,
my english is not so good so i have made a drawing of what i try to do (see attacments)
dim22
March 28, 2016, 8:06am
4
i try to link to trackbar scroll event a sending protocol (1erbit : start messsage 2ème bit direction (send or received), 3emearduino pin, 4eme bit servomotor value)
private void trackBar1_Scroll(object sender, EventArgs e)
{
if (port.IsOpen & checkBox1.Checked)
{
int a = trackBar1.Value;
byte[] buffer = new byte[4];
buffer[0] = Convert.ToByte(16);
buffer[1] = Convert.ToByte(127);
buffer[2] = Convert.ToByte(3);
buffer[3] = Convert.ToByte(a);
port.Write(buff,0,4);
valarti2.Text = "angleepaule2=" + trackBar1.Value.ToString(); } }
arduino code
#include <Servo.h>
Servo articulationa;
Servo articulationb;
//Setup message bytes
byte inputByte_0;
byte inputByte_1;
byte inputByte_2;
byte inputByte_3;
//Setup
void setup() {
articulationa.attach(3);
articulationa.attach(4);
Serial.begin(9600);
}
//Main Loop
void loop() {
//Read Buffer
if (Serial.available() == 4)
{
//Read buffer
inputByte_0 = Serial.read();
delay(100);
inputByte_1 = Serial.read();
delay(100);
inputByte_2 = Serial.read();
delay(100);
inputByte_3 = Serial.read();
delay(100);
}
//Check for start of Message
if(inputByte_0 == 16)
{
//Detect Command type
switch (inputByte_1)
{
case 127:
//Set PIN and value
switch (inputByte_2)
{
case 3:
articulationa.write(inputByte_3); // sets the servo position according to the scaled value
delay(10);
break;
case 4:
articulationa.write(inputByte_3); // sets the servo position according to the scaled value
delay(10);
break;
}
break;
}
//Clear Message bytes
inputByte_0 = 0;
inputByte_1 = 0;
inputByte_2 = 0;
inputByte_3 = 0;
}
}
but it doesn't work:(
Robin2
March 28, 2016, 8:32am
5
You need a more robust way to receive your data. Have a look at Serial Input Basics . There is also a parse example.
...R
dim22
March 28, 2016, 9:49am
6
thanks for help
Owing to your advice i have written this arduino code
#include <Servo.h>
char receivedChars[4];
Servo articulationa;
boolean newData = false;
void setup() {
Serial.begin(9600);
}
void loop() {
recvWithStartEndMarkers();
moveservo();
}
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
// if (Serial.available() > 0) {
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= 4) {
ndx =4 - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void moveservo() {int angle;
if (newData == true) {
if (receivedChars[1]==('3'))
{
int angle = receivedChars[2] - 48;
articulationa.write(angle);}
newData = false;
}
}
and change the c# in
private void trackBar1_Scroll(object sender, EventArgs e)
{
if (port.IsOpen & checkBox1.Checked)
{
int a = trackBar1.Value;
char[] value = trackBar1.Value.ToString().ToCharArray();
byte[] buffer = new byte[4];
buffer[0] = '<';
buffer[1] = '3';
buffer[2] = value[0];
buffer[3] = '>';
port.Write(buff,0,4);
valarti2.Text = "angleepaule2=" + trackBar1.Value.ToString(); } }
system
March 28, 2016, 9:55am
7
if (Serial.available() == 4)
{
//Read buffer
inputByte_0 = Serial.read();
delay(100);
inputByte_1 = Serial.read();
delay(100);
inputByte_2 = Serial.read();
delay(100);
inputByte_3 = Serial.read();
delay(100);
If there are 4 bytes to read, why are you using the ridiculous delay()s between reading value?
Why do you need to send 4 values to define servo number and servo position?
Why do you need checkboxes when you have two sliders? Having radio buttons and one slider would make sense. Having two check boxes and two sliders does not.
but it doesn't work:(
That is just too lame for words. The code on the PC does something. You have not said what it actually does.
The code on the Arduino does something. You have not said what it actually does. All we can surmise is that what the code on the PC causes the code on the Arduino to do is not what you expect. But, we don't know what you expect or what actually happens.
system
March 28, 2016, 10:03am
8
int a = trackBar1.Value;
char[] value = trackBar1.Value.ToString().ToCharArray();
So, if the value in a is 128, value will contain '1', '2', and '8'.
byte[] buffer = new byte[4];
buffer[0] = '<';
buffer[1] = '3';
buffer[2] = value[0];
buffer[3] = '>';
and buffer will contain '<', '3', '1', and '>'.
On the Arduino, receivedChars will contain "31" when the '>' arrives.
if (receivedChars[1]==('3'))
{
int angle = receivedChars[2] - 48;
Since the slider is limited to 0 to 255, the values in the second position of the receivedChars array are limited to '0', '1', or '2'. So, the test will never be true.
Even if it was, because you look in the correct position in the array, AND you use the correct position in the next line of code, the only possible values for angle are 0, 1, and 2.
Is that what you want?
If you are going to send binary data, you must expect to receive binary data. If you are going to expect to receive ASCII data, you must send ASCII data.
Robin2
March 28, 2016, 4:40pm
9
You should make the receivedChars[] array a bit bigger than the amount of data you expect to receive.
...R