Using C# Winforms to control 2 servos, delay issues

Hi,

I'm working on my first project project that controls 2 servos to rotate both horizontally and vertically using the mouse position in winforms.

I'm having an issue where the servos only move after the next move has been made rather than the current move. Also, I'd like to make it so that the servos move at the same time as the mouse movements on screen, which hasn't worked with anything I've tried so far.

I'm not entirely sure about serial communications and I basically just used tutorials to get this far in that respect. To control the angles of the servos I've been joining two bearings from the winform (hence the weird string manipulation) and sending them through the serial connection, then on the arduino end seperating the string to get the two respective angles. I'm not too sure if that's a good approach or not?

Here's my uploaded code:

#include <Servo.h>

Servo servoX;
Servo servoY;

void setup() {
  Serial.begin(9600);
  servoX.attach(8);
  servoY.attach(10);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
}

void loop() {
  //ResetAngle();
  RotateOnInputFromSerial();
}

void ResetAngle()
  {
  int pos = 0;
  servoX.write(pos);
  }

void RotateOnInputFromSerial()
{
  while(Serial.available() > 0){
  String angles = Serial.readString();
  String angleX = angles.substring(0,3);
  String angleY = angles.substring(3,6);
  servoX.write(angleX.toInt());
  servoY.write(angleY.toInt());
  Serial.println("rotated to (degrees): " + angleX + " " + angleY);
  }
}

Here's my winforms code:

using System;
using System.IO.Ports;
using System.Windows.Forms;

namespace ArduinoServoTesto
{
    public partial class Form1 : Form
    {

        bool isConnected = false;
        String[] ports;
        SerialPort port;
        int angleX = 0;
        int angleY = 0;
        string x = "";
        string y = "";

        public Form1()
        {
            InitializeComponent();
            DisableControls();
            GetAvailableComPorts();

            foreach (string port in ports) {
                serialPortComboBox.Items.Add(port);
                Console.WriteLine(port);
                if (ports[0] != null) {
                    serialPortComboBox.SelectedItem = ports[0];
                }
            }
        }

        private void connectButton_Click(object sender, EventArgs e)
        {
            if (!isConnected)
            {
                ConnectToArduino();
            }
            else {
                DisonnectFromArduino();
            }
        }

        private void ConnectToArduino()
        {
            isConnected = true;
            string selectedPort = serialPortComboBox.GetItemText(serialPortComboBox.SelectedItem);
            port = new SerialPort(selectedPort, 9600, Parity.None, 8, StopBits.One);
            //MessageBox.Show(port.PortName);
            port.Open();
            EnableControls();
            connectButton.Text = "Disconnect!";
        }

        private void DisonnectFromArduino()
        {
            isConnected = false;
            DisableControls();
            port.Close();
            connectButton.Text = "Connect!";
        }
        
        private void EnableControls()
        {
            
        }

        private void DisableControls()
        {
            
        }

        void GetAvailableComPorts() {
            ports = SerialPort.GetPortNames();
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            MouseCoordsLabel.Text = e.Location.X + ":" + e.Location.Y;
            int xloc = Convert.ToInt32((((float)e.Location.X) * 180f / (this.Size.Width - 17)));
            int yloc = Convert.ToInt32(((float)e.Location.Y * 180f / (this.Size.Width - 40)));
            x = $"{new string('0', 3 - (xloc.ToString().Length))}{xloc.ToString()}";
            y = $"{new string('0', 3 - (yloc.ToString().Length))}{yloc.ToString()}";
            BearingOutputText.Text = x + y;
            if(isConnected) port.WriteLine(BearingOutputText.Text);
        }

    }
}

apologies for the messy code, this is a work in progress and I've sort of hit a roadblock.

To begin with I would crank up the Serial baudrate. 115200 is the ideal.
Try Arduino/reference/serial communication! There are different ways depending on string end markers, usually Cr/Lf, Cr+Lf etc. are used or not.

Instal some Serial.println( key varialble ) and serial monitor to find out what string has been received.

I would ignore the C# for now
get the servos working by typing commands into the serial monitor (with Serial.println() statements printing key variables at critical points as recommended by @Railroader)
when that is working implement the C# code to transmit the values over serial
have a look at reading-two-sensors-values-in-visual-studio-in-separate-textbox

That's not easy with Windows :frowning:

It were much easier if you use an analog Arduino joystick to control the servos and also send the positions to the PC via Serial.

readString() has a timeout of 1 or 2 seconds (not sure). You send something, readString() reads it but wants to make sure that it's the full message by waiting a bit.

You can read Robin's Serial Input Basics - updated to get some ideas for solid and non-blocking communication.

At the C# side you might want to add some filtering (e.g. only send if x or y change by more than 3 or 5 pixels) to prevent spamming the Arduino with messages.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.