Go Down

Topic: Serial Control of variables on arduino from computer (Read 464 times) previous topic - next topic

dvl12

Hello. I am new to Arduino and I have a problem with controlling it directly from my laptop. I am trying to change a value of variables using serialmonitor while running Arduino. What I managed to do so far is to send a command to the Arduino, but for some unknown reason the main loop is not running continuously; it only runs for a second when a signal is sent. This is my code so far. I would appreciate a lot if some one could direct me the right way please.
Code: [Select]
#include <Servo.h>

Servo servo_1;
Servo servo_2;
Servo servo_3;

//introducing variables
unsigned long serialdata;
int inbyte;

int VAnalog = 0;
int V = 3; // variable to control speed 
int Ampl = 180; // variable to control aplitude
int PD = 0.1; // phase difference variable from 0 to 1

int Drown = 0;
int pos1_old = 0;

int Turn = 0;

int pos1 = 90;
int pos2 = 90;
int pos3 = 90;

void setup()
{
  servo_1.attach(9, 800, 2200);
  servo_2.attach(10, 800, 2200);
  servo_3.attach(11, 800, 2200);
 
  Serial.begin(9600);
}

void loop()
{
//  VAnalog = analogRead(1);
//  V = map(VAnalog, 0, 1023, 0, 7);
//  {
    getSerial();
    switch(serialdata)
    {
      case 1:
        {
          //digital write
          getSerial();
          switch (serialdata)
          {
            case 1:
            {
              getSerial();
              V = serialdata;
              break;
            }
          }
        }
    }
   

 
  float value = millis()/(V*400.0);
 
  if(Drown == 0)
  { 
    pos1 = 90.0+(Ampl/2)*sin((value+0.075)*PI);
    servo_1.write(pos1);
 
    pos2 = 90.0-(Ampl/2)*sin(value*PI);
    servo_2.write(pos2);
  }
 
  if(Drown != 0)
  {
    pos1_old = 90.0+(Ampl/2)*sin(value*PI);
   
    if(pos1_old < 90)
    {
      pos1 = 90.0+(Ampl/(2*Drown))*sin((value+0.075)*PI);
         
      pos2 = 90.0-(Ampl/(2*Drown))*sin(value*PI);     
    }
    else
    {
      pos1 = 90.0+(Ampl/2)*sin((value+0.075)*PI);
     
      pos2 = 90.0-(Ampl/2)*sin(value*PI);
    }
   
    servo_1.write(pos1);
    servo_2.write(pos2);
  }
       
  pos3 = 90.0+(Ampl/3)*sin(value*PI);
  servo_3.write(pos3);
}

long getSerial()
{
  serialdata = 0;
  while (inbyte != '/')
  {
    inbyte = Serial.read();
    if (inbyte > 0 && inbyte != '/')
    {
     
      serialdata = serialdata * 10 + inbyte - '0';
    }
  }
  inbyte = 0;
  return serialdata;
}

Arrch

#1
Mar 04, 2013, 10:55 pm Last Edit: Mar 04, 2013, 10:58 pm by Arrch Reason: 1
but for some unknown reason the main loop is not running continuously; it only runs for a second when a signal is sent.


Here's the reason
 
Code: [Select]
while (inbyte != '/')
 {
   inbyte = Serial.read();
   if (inbyte > 0 && inbyte != '/')
   {
   
     serialdata = serialdata * 10 + inbyte - '0';
   }
 }


This part is blocking, meaning code execution will get stuck in this while loop until you receive a '/'.

Instead of using a blocking while loop, you should be using an if statement to see if there is any Serial data available. You would probably also want a "temoporary serialData" variable that is copied to serialData only after you receive the deliminating character.

dvl12

Arrch thank you for the answer. I changed the while statement to if statement, and now the loop is running, however, I can't change the V variable with a serial monitor now. I think the problem lies in your second proposition, but I am not sure how to implement this?

Arrch

When you make changes to the code, the helpful thing to do is to post the updated code...

dvl12

Sorry for that, here it is:
Code: [Select]
#include <Servo.h>

Servo servo_1;
Servo servo_2;
Servo servo_3;

//introducing variables
unsigned long serialdata;
int inbyte;

int VAnalog = 0;
int V = 3; // variable to control speed 
int Ampl = 180; // variable to control aplitude
int PD = 0.1; // phase difference variable from 0 to 1

int Drown = 0;
int pos1_old = 0;

int Turn = 0;

int pos1 = 90;
int pos2 = 90;
int pos3 = 90;

void setup()
{
  servo_1.attach(9, 800, 2200);
  servo_2.attach(10, 800, 2200);
  servo_3.attach(11, 800, 2200);
 
  Serial.begin(9600);
}

void loop()
{
//  VAnalog = analogRead(1);
//  V = map(VAnalog, 0, 1023, 0, 7);
//  {
    getSerial();
    switch(serialdata)
    {
      case 1:
        {
          //digital write
          getSerial();
          switch (serialdata)
          {
            case 1:
            {
              int serialData = 0;
              getSerial();
              serialData = serialdata;
              V = serialData;
              break;
            }
          }
        }
    }
   

 
  float value = millis()/(V*400.0);
 
  if(Drown == 0)
  { 
    pos1 = 90.0+(Ampl/2)*sin((value+0.075)*PI);
    servo_1.write(pos1);
 
    pos2 = 90.0-(Ampl/2)*sin(value*PI);
    servo_2.write(pos2);
  }
 
  if(Drown != 0)
  {
    pos1_old = 90.0+(Ampl/2)*sin(value*PI);
   
    if(pos1_old < 90)
    {
      pos1 = 90.0+(Ampl/(2*Drown))*sin((value+0.075)*PI);
         
      pos2 = 90.0-(Ampl/(2*Drown))*sin(value*PI);     
    }
    else
    {
      pos1 = 90.0+(Ampl/2)*sin((value+0.075)*PI);
     
      pos2 = 90.0-(Ampl/2)*sin(value*PI);
    }
   
    servo_1.write(pos1);
    servo_2.write(pos2);
  }
       
  pos3 = 90.0+(Ampl/3)*sin(value*PI);
  servo_3.write(pos3);
}

long getSerial()
{
  serialdata = 0;
  if (inbyte != '/')
  {
    inbyte = Serial.read();
    if (inbyte > 0 && inbyte != '/')
    {
     
      serialdata = serialdata * 10 + inbyte - '0';
    }
  }
  inbyte = 0;
  return serialdata;
}

Arrch

You're still not checking if there is available data before reading from the serial port (Serial.available()). The psuedo code would look something like this:

Code: [Select]
if serial data available
  read data
  if data is deliminator
    set serial variable to temp serial variable
    set temp serial variable to 0
  else
    do arithemetic with temp serial variable


Alternatively, you can make it easier on yourself by using Serial.parseInt()

zoomkat

Servo test code that captures servo position commands sent from the serial monitor.

Code: [Select]

//zoomkat 11-22-12 simple delimited ',' string parse
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added

String readString;
#include <Servo.h>
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo

void setup() {
  Serial.begin(9600);

  //myservoa.writeMicroseconds(1500); //set initial servo position if desired

  myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or combined like 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
         readString=""; //clears variable for new input
      }
    } 
    else {     
      readString += c; //makes the string readString
    }
  }
}

Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

zoomkat thats awesome and seems like a possible solution for what Im trying to do getting in serial from vvvv.  Im trying to get some very basic values in via vvvv and I have the option to intersperese or use whatever delimiter I need.  Ive got some servo movement but its pretty jumpy..am i missing something to make this work correctly?

I attached the v4 file in case you happen to deal with it.

Go Up