Pages: [1]   Go Down
Author Topic: Serial Control of variables on arduino from computer  (Read 423 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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;
}
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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.
« Last Edit: March 04, 2013, 04:58:00 pm by Arrch » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry for that, here it is:
Code:
#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;
}
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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()
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9541
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
//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
    }
  }
}

Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Wien Austria
Offline Offline
Newbie
*
Karma: 0
Posts: 46
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

* RS232 (Devices String)_adam_through to vvvv.v4p (15.71 KB - downloaded 3 times.)
Logged

Pages: [1]   Go Up
Jump to: