Serial Monitor and input/reading variables to determine the combination of code

Hello, I am working on a school project, and I kind of went into a wall with some Arduino coding.

Overview and understanding of my project: I want to build an dispenser with servo controlling, and a rotating block (rotated by a motor and posistion determinated by a Rotary Encoder). But this is all good, and i fully understand how to set this up, both build and code with the Arduino Uno. But a key function of this project would be to determine how many of each object should be dropped down from the dispenser. (We are building a dispenser holding and dropping light weighted metal balls).

My problem and question is: Is it possible to somehow code something within the Arduino (without comming into coding an interface), to determine how to tell the arduino how many of each material there should be dropped down. Let's say i want to drop 4 balls of the first dispenser that comes in the rotation path, and after that i want 5 of the next material. Would I be able to somehow tell the Arduino (maybe through the serial monitor?) this without having to recode and upload a new program each time?

Thank you in advance! And sorry for the bad English.

Rommar: Let's say i want to drop 4 balls of the first dispenser that comes in the rotation path, and after that i want 5 of the next material. Would I be able to somehow tell the Arduino (maybe through the serial monitor?) this without having to recode and upload a new program each time?

YES.

But you need to provide more detail if you want more specific advice. How does the Arduino control how many balls are dropped? How does the Arduino coordinate the number of balls with the appropriate dispenser? How will the Arduino coordinate the data from the PC with the appropriate dispenser? How much time is there between drops? How often do you want to update data from the PC? AND anything else that may be relevant

...R

Well simply i want to build me through most of the "problems" you have listed below. I have managed to construct a cylinder with just enough space between two servos to hold one ball. Therefor i want to manage how many balls drops, and coordinate with the Ardunio, but dropping one at a time.

The lower servo runs, so there is a passage through the dispenser, and it goes back to it previous stage. After that the upper servo runs, so a new ball can drop down, and the servo goes to previous stage. The system repeats itself.

And i want the lowest possible time between drops.

The school project is all about trying to make a workstation more automatic. Therefor I just have to show, how something can be done automatic. So to update the data from the PC, can be done anything arround after 5 cycles to maybe 1000. Therefor I just want to have it so it can recycle the same data atleast 2 times, before I give it some new.

Simply I tried making a simple system for the Arduino, where each LED symbols a motor. This is where ROT, rotates the platform, stops under the dispenser, one servo opens, a ball drop, the servo closes. The other servo opens, and drops a ball, and the servo closes. The platform rotates back. So 2 balls dropped.

int ROT = 13; int NED = 10; int OP = 9; int state; int flag=0;

void setup() { pinMode(ROT, OUTPUT); pinMode(NED, OUTPUT); pinMode(OP, OUTPUT); Serial.begin(9600); }

void loop() { if (Serial.available() > 0) { state = Serial.read(); flag=0; } if(state == '1') { if (flag == 0) { Serial.println("start"); digitalWrite(ROT, HIGH); delay(2000); digitalWrite(ROT, LOW); delay(2000); digitalWrite(NED, HIGH); delay(2000); digitalWrite(NED, LOW); delay(2000); digitalWrite(OP, HIGH); delay(2000); digitalWrite(OP, LOW); flag=1; } } }

Ofcourse i could just repeat this cycle with another "state", but i want it to be so I can write a number of ball dropped, without having to make a ton of code for each combination of ball drops from the appropriate dispenser.

And just to remind, im not an expert in arduino code, I have only had 1 day a week for half a year to study in both construction with metal and coding an arduino. So I really appreciate all the help i can get.

First, you need to expand your Arduino programming knowledge by studying several of the example programs that come with the Arduino IDE. You should probably learn about FOR loops and maybe arrays.

You might also get some useful ideas from planning and implementing a program. And the examples in serial input basics should help for receiving data from your PC.

Rather than trying to design a complete program you should try each of the parts in separate short programs - rotating the dispensers, dropping 1 ball, dropping a number of balls, receiving data from the PC etc. When you are confident you can do all the pieces it will be time to join them into a single project.

Using a servo to control the balls will make the coding simple.

And i want the lowest possible time between drops

You need to put a number on this in order to plan your program. Do you want one per second, 10 per second, or what?

I still don’t understand the relationship between the dispenser and the number of balls. Have you (for example) 4 dispensers and they should get (say) 3, 5, 7 and 4 balls respectively. Would it matter if the 5 balls fall into dispenser number 3?

If you upload new data from the PC do you have to ensure that the nuumbers of balls fall into the correct dispensers?

…R

How does the servo ball dispenser operate?

Thank you so much. I will start looking through the things you have giving me by now, and return when i get a little further in the project!

Okay, so I have come a little further into the project, to the point where i have tested a system where a potentiometer turn an LED to “low” when it reach a surtain amount. This LED symbolises a motor, and this is due to i have not yet got a working motor to test with.
After the LED is turned to “LOW”, a servo will start sweeping from 0 to 90 degree and back. Here one ball will be dropped into the rotating object that the motor will be rotating. After this a new servo will start sweeping from 0 to 90 degree and back. Here a new ball will be mounted between both of the servos. And the Servo system can run again if needed.
The code for now:

//potentiometer pins and variable
const byte potPin = A0;
int potValue;

//Motor that is symbolised with a LED
int LED1 = 10;

//Servo confiq
#include <Servo.h> 
Servo myServoDrop;                  
Servo myServoMount;
int pos = 0;    

void setup()
{
  Serial.begin(9600);
  pinMode(LED1, OUTPUT);
  myServoDrop.attach(9);  
  myServoMount.attach(11);
}

void loop()
{
readPotentiometer();
Serial.println(potValue);
LED2();
delay(50);
ServoDrop();
delay(500);
ServoMount();
}

//Read the potentiometer
void readPotentiometer() 
{
  potValue = analogRead(potPin);
}

//If statement, when the potentiometer reach x amount, turn the motor off
void LED2()
{
  if (potValue < 200)
  {
    digitalWrite(LED1, HIGH);
  }
  else
    {
      digitalWrite(LED1, LOW);
    }
  }

//If statement, when the potentiometer reach same x amount, 
//drop the first ball into the rotating object
//that is rotated by the motor
void ServoDrop() { 
  if (potValue >= 200)
  {
  for(pos = 0; pos <= 90; pos += 1)  
  {                                  
    myServoDrop.write(pos);              
    delay(15);                       
  } 
  for(pos = 90; pos>=0; pos-=1)     
  {                                
    myServoDrop.write(pos);               
    delay(15);                      
  } 
}
}

//When the ball is dropped, the second Servo mounts the next ball
//ready to getting dropped into the rotating object
void ServoMount() 
{ 
    if (potValue >= 200)
  {
  for(pos = 0; pos <= 90; pos += 1)  
  {                                  
    myServoMount.write(pos);               
    delay(15);                       
  } 
  for(pos = 90; pos>=0; pos-=1)    
  {                                
    myServoMount.write(pos);              
    delay(15);                       
  } 
}
}

But here is my problems:
I can’t think of a way to tell the Arduino Uno how many times the “servo system” should run.
Robin you send something about the Serial Input, but i don’t think I quite understood how to implement it in my code, i could imagine is has something to do with some variables?

Also; I do not know how to get the LED (motor) to be set to “HIGH”, give it a signal to run, after my “servo system” has dropped the correct amount of balls.

And the last; How do I make so my potentiometer can have more “stop” values, so that my motor can stop run at both 200 and maybe again at 400?

Thank you in advance!

Take things a piece at a time

You need a variable that is incremented every time a servo is run in order to keep track of how many times.
My reference to serial input was based on the assumption that you want to be able to send a number to the Arduino - but leave that for later.

After the count has reached its target you can set the pin to drive the LED (motor)

You can get as many positions from your potentiometer as you want with a series of IF ELSE statements

if (potValue > 800) {
   // do something
}
else if (potValue > 600) {
   // do something
}
else if (potValue > 300) {
  // do something
}
else {
   // do something
}

From your questions I get the impression that you have not gone through the process of writing down in plain language the steps needed to make your system function. I find that writing them down, one step per line, is a great way of seeing the logic without being confused by computer code.

By the way, I wonder is there any need for your servos to move in steps if all they are intended to do is release a ball.

…R

Thank you again Robin! I think i see the picture in the code you send me now. But how do I get the Servos to stop working after x amount of cycles, and then turn on the LED again? My acutal problem right now is that i can have the motor running and turning an object plus the potentiometer, but as soon as the potentiometer get to the position, it ofcourse stops the motor from running, but the servos just keep doing their endless cycle.

From your questions I get the impression that you have not gone through the process of writing down in plain language the steps needed to make your system function. I find that writing them down, one step per line, is a great way of seeing the logic without being confused by computer code.

And yes I did do this, I just didn't include it in this post, maybe I was mistaken in not doing so. But it acutally helped me a lot, and also i tried and seperate the function into smaller pits, so that way I went into a lot of fever errors and such.

And for you question; No there is no reason for the servos to run in steps, i just figured it would look more intuitive to the construction if it only ran 90 degree out.

Sorry if im rushing ahead, I just don't have any idea of how to get going from here on.

EDIT: Maybe im totally mistaken, but that way of stopping the servos? (my question). Would that be to lets say, tell the arduino what a sertain varible has of amount through input (lets say x). Then make as you said a new varibale that increment (y) by 1 each time the servo cycles has gone through once, and check if this increment varible (y) is equeal to (x), then if it is, it should force the arduino to turn on the LED so the motor can turn the potentiometer and then of course an else if statement like you said to make more positions?

A simple way to manage the counting is to create a little function to control the servo.

void dropBall() {
   myServoDrop.write(90);
   delay(100);
   myServoDrop.write(0);
}

Then you can call that function as many times as required

if (numDrops < totalDrops) {
   dropBall();
   numDrops ++;
}

It would be useful to post your list of steps as then we can understand how you are thinking about the project.

…R

Thank you so much for the help up until now Robin, I have come a long way by now thanks to you.
So what I have intended to do is:

Send message over serial port asking for a ball combination
Serial Read - read the combination send, and check if it is correct.
If correct, start loop with:

  • ReadPotentiometer
  • Send a signal to run a motor
  • Stop at different positions
  • When stopped, read one part of the combination as inputed
  • Use this to repeat a sequence of
void dropBall() {
   myServoDrop.write(90);
   delay(1000);
   myServoDrop.write(0);
   delay(1000);
}
  • When it has completed the seuqence of different positions and balldrops, stop loop, and ask for a new combination

Up until now i have done everything except things with the serial port, and the stop loop function.
So basicly I need to make the “totalDrops” (see code below) which is right now just an int variable, to something that can be written into the serial port and read by the Arduino.

  if (potValue > 400)
  {
    digitalWrite(LED1, LOW);
    if (numDrops < totalDrops) 
    {
       dropBall();
       numDrops ++;
    }

I tried looking into the post from Robin “Serial Input Basics” and the code example “python”, and I figured as much as I need to make some binary input, and also some start and end markers to secure that a code has been send correctly. But to be honest i couldn’t quite get my head arround to implement it in my own code.

Thank you in advance.

From Reply #10

When stopped, read one part of the combination as inputed

I don't quite understand this.

Can you show a typical example of the data you want to send? And what it is supposed to do?

If you just want to send data using the Serial Monitor you do not need my Python code and the 3rd example in serial input basics should be suitable

But without a better idea of what you want to send I can't be more specific.

It would also help if you can tell me what you don't understand in those examples.

...R

Okay so I sat down and got things straight on what I need to do and what I already have done up until now.
So to refresh, I want to make a dispenser system, that is able to drop balls.
I have managed to succesfully drop multiple balls using Servos, and also to rotate and stop a motor again by rotating a potentiometer.

What I need:
Somehow to tell the Arduino how many times I need repeat the system of servo drops listed in another reply (ballDrop).
I tested the example 3 as requested by Robin, and it fully worked for what I need to do right now.
(Maybe later we can talk about implementing something with maybe writing in the serialport and get the arduino to read it and convert to an interger)
As of now i have created the following:

//potentiometer pins and variable
const byte potPin = A0;
int potValue;

//Motor that is symbolised with a LED
int LED1 = 10;

//Servo confiq
#include <Servo.h> 
Servo myServoDrop;                  
Servo myServoMount;
int pos = 0;    
int totalDrops;
int numDrops = 0;
int totalDrops2;
int numDrops2 = 0;

// Serialport configure
char receivedChars[] = "Number of drops in order, 5, 5" ;
char messageFromPC[32] = {0};
char recvChar;
char endMarker = '>';
boolean newData = false;

void setup()
{
  Serial.begin(9600);
  Serial.println("<Arduino is ready>");
  pinMode(LED1, OUTPUT);
  myServoDrop.attach(9);  
  myServoMount.attach(11);
  parseData();
}

void loop()
{
readPotentiometer();
Serial.println(potValue);
delay(50);
RunandStop();
  }

// dropBall that simply sweeps a servo
void dropBall() {
   myServoDrop.write(90);
   delay(1000);
   myServoDrop.write(0);
   delay(1000);
}

// A potentiometer to determine position
void readPotentiometer() 
{
  potValue = analogRead(potPin);
}

// If statements for which potentiometer values the motor stops
// and repeat "dropBall" as many times as inputed
void RunandStop()
{
  if (potValue > 400)
  {
    digitalWrite(LED1, LOW);
    if (numDrops2 < totalDrops2) 
    {
       dropBall();
       numDrops2 ++;
    }
  else 
    {
      digitalWrite(LED1, HIGH);
    }
  }
  else if (potValue > 200)
  {
    digitalWrite(LED1, LOW);
    if (numDrops < totalDrops) 
    {
       dropBall();
       numDrops ++;
    }
  else 
    {
      digitalWrite(LED1, HIGH);
    }
  }
else 
  {
  digitalWrite(LED1, HIGH);
  }  
}

//Convert the message that is recieved
//to int variables "totalDrops" and "totalDrops2"
void parseData() {
  char * strtokIndx; 
  
  strtokIndx = strtok(receivedChars,",");      // Get the First part
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  totalDrops = atoi(strtokIndx);     // Convert number to integer, that determines max number of drops
  
  strtokIndx = strtok(NULL, ","); 
  totalDrops2 = atoi(strtokIndx);     
  // convert this part to a new interger, 
  // that determines max number of drops another dispenser system
}

Now: Is there any way I can repeat this proces, say like 50 times?
When I tested it, I came upon the problem that the numDrop value is stored as it should. But to make the arduino forget this value i need to reopen the Serial monitor. Is there a way for me to make the Arduino forget this at a certain potValue? So in that way I can upload a program that have:
(From my code)
“char receivedChars = “Number of drops in order, 2, 4, 50” ;” where 2 is the first amount of drops, 4 is the second amount of drops at another location, and 50 is how many times this cycle should run.

From Reply #10
Quote
When stopped, read one part of the combination as inputed
I don’t quite understand this.

That was just me thinking that the Arduino needed to read a part of the input each time it should drop something, but when I read the “serial input basics” again, I found out that the values got stored, and in that way, read the exact value needed.

Rommar:
Now: Is there any way I can repeat this proces, say like 50 times?

I am a bit confused.

As things stand you have a fixed number of balls - 5 and 5
Do you want to repeat that 50 times - i.e. 50 times with the same numbers

OR

Do you want to give the operator the chance to enter 50 different sets of numbers.

Separately —

If you want to get numbers from the operator I would add some code like this

Serial.println("Please enter 2 new numbers - for example <6,4>")
boolean newData = false;
while (newData == false) {
   recvWithStartEndMarkers(); // as in serial input basics
}

This is fairly simple, but it should give you the idea

…R

I am a bit confused.

As things stand you have a fixed number of balls - 5 and 5
Do you want to repeat that 50 times - i.e. 50 times with the same numbers

This I figured out how to do after a bit of testing. Simply just making a new integer and making it count to a certain number. I just had to get my thinking straight :D.

But now I have come to the part, where I just need to write to Serial Monitor instead of manually giving the arduino the message, and uploading the program.
I tried making a system where an LED should light up as soon as it gets some data.
I used the example code from the post above by Robin.

const byte numChars = 32;
byte receivedChars[numChars];

char messageFromPC[32] = {0};
boolean newData = false;

int LED = 13;

void setup ()
{ 
   Serial.begin(9600);
 Serial.println("<Arduino is ready>");
 pinMode(LED, OUTPUT);
 digitalWrite (LED, LOW);
}

void loop ()
{
 while (newData == false)
{
  recvWithStartEndMarkers();
  showNewData();
} 
  digitalWrite(LED, HIGH);
} 

void recvWithStartEndMarkers() {
	static boolean recvInProgress = false;
	static byte ndx = 0;
	char startMarker = '<';
	char endMarker = '>';
	byte 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 >= numChars) {
					ndx = numChars - 1;
				}
			}
			else {
				receivedChars[ndx] = '\0'; // terminate the string
				recvInProgress = false;
				ndx = 0;
				newData = true;
			}
		}

		else if (rc == startMarker) {
			recvInProgress = true;
		}
	}
}

void showNewData() {
	
		Serial.print("This just in ... ");
		Serial.println((char*)receivedChars);
		newData = false;
	}

But the problem is here: The arduino reads the message totally fine, and it also parse the data correctly (tried this in another code, and it worked fine), but after it has recieved the message it tries to find a new message and therefor deleting the current Data. So simply it tries to read messages that arent comming, and therefor the function showNewData, just keep getting through as 0, instead of the actual command that was sent (for example <3,4>, would be two lines 3 and 4).

Any idea of how to fix, so the arduino only reads what is written to it?

A simple way to send a value to the arduino (delimited with a comma), then convert the character value sent into an integer for use.

//zoomkat 3-5-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

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

  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-delomit-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 700, or 1500, or 2000,
  //or like 30, or 90, or 180,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >0) {
        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);
          myservo.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          myservo.write(n);
        }

        //do stuff with the captured readString 
        readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

You need to make use of the variable newData to manage the reading of the next message. It won't read a new message until you change newData to false. That's the purpose of the line

while (Serial.available() > 0 && newData == false) {

As things stand newData is set to false immediately after the data is printed to the screen. You need to make your other code happen before you change that value to false. You could do that by calling another function immediately before the call to showNewData().

...R