Go Down

Topic: Using letter from a string to select which function (Read 228 times) previous topic - next topic

splext

Hi all,

I am fairly new to arduino, and BRAND NEW to this forum, so hi, and apologies if this is in the wrong place or if I am doing anything wrong.

I am working on a project which is basically an arm (built of cardboard and 3 x Servos), with a stylus in the end, which I want to move to each letter on a physical keyboard, depending on what is typed in the Serial.

There are a whole bunch of other parts to this (I intend to use a GSM Shield to be able to text a string to the serial, which will then type out on the RL keyboard.

I know the concept seems odd and long winded, but this is my target so bare with me.

The current issue I am having; is that regardless of which letter is typed, it ends up running "a". I assume its a problem with my IF statement or perhaps I should be using a different statement for this? Yes I plan on doing the whole alphabet once i can get it to choose between the first two letters.

I have commented a bunch of the code to simplify to one servo while i fault find currently.

As the code is... I want the pan servo to turn to 43  degrees if an "a" is written, and 180 degrees if a "b" is written.

Any help is much appreciated, and I will try and answer any questions I have.

Thanks in advance, code below.

Spice

Code: [Select]
#include <Servo.h>

Servo pan;
Servo tilt;
Servo tap;

String msg = "What do you want to type?"; //Serial user message
String userInput = ""; //holder for the inputted string
char userInputArray[4]; //conversion of string to array
char letter1;
char letter2;
char letter3;
int posPan;
int posTilt;
int posTap;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pan.attach(9);
tilt.attach(10);
tap.attach(11);

pan.write(90); //intialise servos to center
tilt.write(90);
tap.write(90);

}

void loop() {
  // put your main code here, to run repeatedly:
  letter1=""; //initialise letter1
  Serial.println(msg);
while (Serial.available()==0){
} //Ask for input
getUserInput(); //attach string to letters
letter1Select(); //find out which letter is in letter1 and move to it
resetArms(); //move back to centre
}

void getUserInput(){
   userInput = Serial.readString();
//Serial.println(userInput); //See if userInput is working
userInput.toCharArray(userInputArray,4);
//Serial.println(userInputArray); //See if userInputArray is working
letter1 = userInputArray[0];
letter2 = userInputArray[1];
letter3 = userInputArray[2];
Serial.println(letter1);
//Serial.print(letter2); // Check letters are working
//Serial.println(letter3);
}

void letter1Select(){
  if (letter1 = "a"){
    tapa();
  }
  else if (letter1 = "b"){
    tapb();
  }
  else {
    resetArms();
}
}

  void tapa() {
    for (posPan =90; posPan >=43; posPan -= 1){
      pan.write(posPan);
    delay(40);
    }
//     for (posTap =90; posTap >=50; posTap -= 1){
//      tap.write(posTap);
//    delay(40);
//    }
//    for (posTilt =90; posTilt <=114; posTilt += 1){
//      tilt.write(posTilt);
//    delay(40);
//    }

  }

    void tapb() {
    for (posPan =90; posPan <=180; posPan += 1){
      pan.write(posPan);
    delay(40);
    }
//     for (posTap =90; posTap >=40; posTap -= 1){
//      tap.write(posTap);
//    delay(40);
//    }
//    for (posTilt =90; posTilt >=60; posTilt -= 1){
//      tilt.write(posTilt);
//    delay(40);
//    }
//    for (posTap =40; posTap >=20; posTap -= 1){
//      tap.write(posTap);
//    delay(20);
//  }
//  for (posTap =20; posTap <=40; posTap += 1){
//      tap.write(posTap);
//    delay(40);
//    }
    }
   
  void resetArms(){
    pan.write(90);
    tilt.write(90);
    tap.write(90);
  }
//}

UKHeliBob

Code: [Select]
  if (letter1 = "a")
Whoops !

You are setting letter1 to "a" not comparing it to "a"
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

ToddL1962

Code: [Select]
  if (letter1 = "a")
Whoops !

You are setting letter1 to "a" not comparing it to "a"
Also use single quotes for char compare

splext

Code: [Select]
  if (letter1 = "a")
Whoops !

You are setting letter1 to "a" not comparing it to "a"
Was hoping it was something basic. Thanks. I will amend and retry

UKHeliBob

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

splext

Hi all,

So I want to control 3 servos to go to certain positions based on what is input in the Serial monitor.

So the user can type anything, but I want it to cut  to the first 3 letters, which it does.

it then takes each letter separately and goes through the function of said letter.

The issue I am having, is probably with my for loop. Irrelevant of what is put, it seems to run the last ELSE statement and resets.

All the servos work fine and are linked fine, I just can't figure out where my mistake is.

I wondered if "a" string, == the same as a user inputted letter a?

Thanks in advance

Spice

Code: [Select]
#include <Servo.h>

Servo pan;
Servo tilt;
Servo tap;

String msg = "What do you want to type?"; //Serial user message
String userInput = ""; //holder for the inputted string
char userInputArray[4]; //conversion of string to array
char letter1;
char letter2;
char letter3;
int posPan;
int posTilt;
int posTap;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pan.attach(9);
tilt.attach(10);
tap.attach(11);

pan.write(90); //intialise servos to center
tilt.write(90);
tap.write(90);

}

void loop() {
  // put your main code here, to run repeatedly:
  letter1=""; //initialise letter1
  Serial.println(msg);
while (Serial.available()==0){
} //Ask for input
getUserInput(); //attach string to letters
letter1Select(); //find out which letter is in letter1 and move to it
resetArms(); //move back to centre
}

void getUserInput(){
   userInput = Serial.readString();
//Serial.println(userInput); //See if userInput is working
userInput.toCharArray(userInputArray,4);
Serial.println(userInputArray); //See if userInputArray is working
letter1 = userInputArray[0];
letter2 = userInputArray[1];
letter3 = userInputArray[2];
//Serial.println(letter1);
//Serial.print(letter2); // Check letters are working
//Serial.println(letter3);
}

void letter1Select(){

  if (letter1 == "a"){
    tapa();
  }
  else if (letter1 == "b"){
    tapb();
  }
//  else if (letter1 == "c"){
//    tapc();
//  }
//  else if (letter1 == "d"){
//    tapd();
//  }
//  else if (letter1 == "e"){
//    tape();
//  }
//  else if (letter1 == "f"){
//    tapf();
//  }
//  else if (letter1 == "g"){
//    tapg();
//  }
  else {
    resetArms();
}
}

  void tapa() {
    //Serial.println("yes");
    for (posPan =90; posPan >=63; posPan -= 1){
      //Serial.println("yes2");
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap <=100; posTap += 1){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=60; posTilt -= 1){
      tilt.write(posTilt);
      delay(40);
      }
  }

    void tapb() {
      //Serial.println("no, b");
    for (posPan =90; posPan <=180; posPan += 1){
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap >=40; posTap -= 1){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=60; posTilt -= 1){
      tilt.write(posTilt);
      delay(40);
      }
    for (posTap =40; posTap >=20; posTap -= 1){
      tap.write(posTap);
      delay(20);
      }
  for (posTap =20; posTap <=40; posTap += 1){
      tap.write(posTap);
      delay(40);
      }
    }

    void tapc() {
    for (posPan =90; posPan <=180; posPan += 1){
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap >=40; posTap -= 1){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=60; posTilt -= 1){
      tilt.write(posTilt);
      delay(40);
      }
    for (posTap =40; posTap >=20; posTap -= 1){
      tap.write(posTap);
      delay(20);
      }
  for (posTap =20; posTap <=40; posTap += 1){
      tap.write(posTap);
      delay(40);
      }
    }
    void tapd() {
    for (posPan =90; posPan <=180; posPan += 1){
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap >=40; posTap -= 1){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=60; posTilt -= 1){
      tilt.write(posTilt);
      delay(40);
      }
    for (posTap =40; posTap >=20; posTap -= 1){
      tap.write(posTap);
      delay(20);
      }
  for (posTap =20; posTap <=40; posTap += 1){
      tap.write(posTap);
      delay(40);
      }
    }

    void tape() {
    for (posPan =90; posPan <=180; posPan += 1){
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap >=40; posTap -= 1){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=60; posTilt -= 1){
      tilt.write(posTilt);
      delay(40);
      }
    for (posTap =40; posTap >=20; posTap -= 1){
      tap.write(posTap);
      delay(20);
      }
  for (posTap =20; posTap <=40; posTap += 1){
      tap.write(posTap);
      delay(40);
      }
    }
    void tapf() {
    for (posPan =90; posPan <=180; posPan += 1){
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap >=40; posTap -= 1){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=60; posTilt -= 1){
      tilt.write(posTilt);
      delay(40);
      }
    for (posTap =40; posTap >=20; posTap -= 1){
      tap.write(posTap);
      delay(20);
      }
  for (posTap =20; posTap <=40; posTap += 1){
      tap.write(posTap);
      delay(40);
      }
    }
    void tapg() {
    for (posPan =90; posPan <=180; posPan += 1){
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap >=40; posTap -= 1){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=60; posTilt -= 1){
      tilt.write(posTilt);
      delay(40);
      }
    for (posTap =40; posTap >=20; posTap -= 1){
      tap.write(posTap);
      delay(20);
      }
  for (posTap =20; posTap <=40; posTap += 1){
      tap.write(posTap);
      delay(40);
      }
    }
  void resetArms(){
    //Serial.println("reset");
    pan.write(90);
    tilt.write(90);
    tap.write(90);
  }

wildbill

Put single quotes around your letters 'a' not "a".

UKHeliBob

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

splext

I'm back again!

Project is working great, thanks for the help so far!

So if you remember/read above, I am looking to check 3 characters in a user inputted string, and move to those set positions.

Currently i'm running a letter1Select function to go through the alphabet, discover which letter is saved in letter1, and execute.

My question is: I am wanting to write a for statement to be able to reuse this function for letters 2 and 3  (to save having to rewrite run Tapa, runTapb, etc over and over.

I assume something like: for (letter(n), n+=1) although not exactly that obviously.

Can someone help with how i could format this to work logically?

Thanks in advance

Spice

Code: [Select]
#include <Servo.h>

Servo pan;
Servo tilt;
Servo tap;

String msg = "What do you want to type?"; //Serial user message
String userInput = ""; //holder for the inputted string
char userInputArray[4]; //conversion of string to array
char letter1;
char letter2;
char letter3;
int posPan;
int posTilt;
int posTap;
intLetter;

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pan.attach(9);
tilt.attach(10);
tap.attach(11);

pan.write(90); //intialise servos to center
tilt.write(90);
tap.write(90);

}

void loop() {
  // put your main code here, to run repeatedly:
  letter1=""; //initialise letter1
  Serial.println(msg);
while (Serial.available()==0){
} //Ask for input
getUserInput(); //attach string to letters
letter1Select(); //find out which letter is in letter1 and move to it
resetArms(); //move back to centre
}

void getUserInput(){
   userInput = Serial.readString();
//Serial.println(userInput); //See if userInput is working
userInput.toCharArray(userInputArray,4);
Serial.println(userInputArray); //See if userInputArray is working
letter1 = userInputArray[0];
letter2 = userInputArray[1];
letter3 = userInputArray[2];
//Serial.println(letter1);
//Serial.print(letter2); // Check letters are working
//Serial.println(letter3);
}

void letter1Select(){
  if (letter1 == 'a'){
    tapa();
  }
  else if (letter1 == 'b'){
    tapb();
  }
  else if (letter1 == 'c'){
    tapc();
  }
  else if (letter1 == 'd'){
    tapd();
  }
  else if (letter1 == 'e'){
    tape();
  }
  else if (letter1 == 'f'){
    tapf();
  }
  else if (letter1 == 'g'){
    tapg();
  }
  else if (letter1 == 'h'){
    taph();
  }
  else if (letter1 == 'i'){
    tapi();
  }
  else if (letter1 == 'j'){
    tapj();
  }
  else if (letter1 == 'k'){
    tapk();
  }
  else if (letter1 == 'l'){
    tapl();
  }
  else if (letter1 == 'm'){
    tapm();
  }
  else if (letter1 == 'n'){
    tapn();
  }
  else if (letter1 == 'o'){
    tapo();
  }
  else if (letter1 == 'p'){
    tapp();
  }
  else {
    resetArms();
}
}

  void tapa() {
    for (posPan =90; posPan >=62; posPan -= 5){
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap <=105; posTap += 5){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=17; posTilt -= 10){
      tilt.write(posTilt);
      delay(40);
      }
     for (posTilt =17; posTilt <=90; posTilt += 8){
      tilt.write(posTilt);
      delay(40);
      }
     for (posPan =62; posPan <=90; posPan += 5){
      pan.write(posPan);
      delay(40);
      }
  }

    void tapb() {
    for (posPan =90; posPan <=100; posPan += 5){
      pan.write(posPan);
      delay(40);
      }
     for (posTap =90; posTap >=55; posTap -= 5){
      tap.write(posTap);
      delay(40);
      }
    for (posTilt =90; posTilt >=20; posTilt -= 10){
      tilt.write(posTilt);
      delay(40);
      }
    for (posTilt =20; posTilt <=90; posTilt += 8){
      tilt.write(posTilt);
      delay(40);
      }

    }

  void resetArms(){
    //Serial.println("reset");
    pan.write(90);
    delay(80);
    tilt.write(90);
    delay(80);
    tap.write(90);
    delay(80);
  }

taterking

#9
May 23, 2020, 02:33 am Last Edit: May 23, 2020, 02:43 am by taterking
here is a much cleaner way to send numbers to a function according to a keypress. this is just a quick example to show the idea. if you press a,b or c in this sketch it sends the corresponding numbers to a function.

Code: [Select]


// 97 is ascii for letter a
// 98 is ascii for letter b
// 99 is ascii for letter c
int numbers [3][4]  = {{97,30,40,50},{98,60,70,88},{99,55,40,60}};
void setup() {Serial.begin(9600);}

void loop() {
 if(Serial.available()){ 
 byte key = Serial.read();
  byte b = 3;
  while(b>0){b--;
  if(key==numbers[b][0]) {
    myfunction(numbers[b][1],numbers[b][2],numbers[b][3]);break;
    }}}}

    void myfunction(int a,int b, int c){
      Serial.print(a);  Serial.print(b);  Serial.print(c);
      }




in the arrays at the top the first number is the ascii number for the keyboard character so the code can look for it. after finding a match it sends the next three numbers in the array to the function. obviosly you can use these numbers to move your motors however you wish. and you can add as many characters as you want without writing any more lines of code.
Building robots to take over the world.

splext

Thanks Taterking, it looks alot sleaker and should work much better.

my issue now is that depending on whether the 'int a' is >90 or <90 i need it to run up or down (so basically a different for loop either way.

Im not sure what i'm missing with this one, but currently the a,b and c, transfer over into the function fine, but regardless of what 'a' is, it doesn't run either of the for loops. I might have just tied myself in knots being inside a for loop inside an if loop inside a function; but any idea what I've missed would be fab.

Thanks again in advance!

Code: [Select]
#include <Servo.h>

Servo pan;
Servo tilt;
Servo tap;

String msg = "What do you want to type?"; //Serial user message
String userInput = ""; //holder for the inputted string
char userInputArray[4]; //conversion of string to array
char letter1;
char letter2;
char letter3;
int posPan;
int posTilt;
int posTap;
int Letter;
int movements [3][4] = {{97,62,105,17},{98,100,55,20},{99,77,65,20}};


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
pan.attach(9);
tilt.attach(10);
tap.attach(11);

pan.write(90); //intialise servos to center
tilt.write(90);
tap.write(90);

}

void loop() {
  // put your main code here, to run repeatedly:
  letter1=""; //initialise letter1
  Serial.println(msg);
while (Serial.available()==0){
} //Ask for input
getUserInput(); //attach string to letters
letter1Select(); //find out which letter is in letter1 and move to it
resetArms(); //move back to centre
}

void getUserInput(){
   userInput = Serial.readString();
   userInput.toLowerCase();
//Serial.println(userInput); //See if userInput is working
userInput.toCharArray(userInputArray,4);
Serial.println(userInputArray); //See if userInputArray is working
letter1 = userInputArray[0];
letter2 = userInputArray[1];
letter3 = userInputArray[2];
}


void letter1Select(){
  //byte key1 = letter1;
  byte b = 29;
  while (b>0) {b--;
    if (letter1==movements[b][0]){
      tapLetter(movements[b][1],movements[b][2],movements[b][3]); break;
    }
  }
}

void tapLetter(int a, int b, int c){
  if (a <= 89){
      for (posPan =90; posPan <=a; posPan += 4){
          pan.write(posPan);
          delay(40);
      }}
  else if (a >= 90){
    for (posPan =90; posPan >=a; posPan -= 4){
      pan.write(posPan);
      delay(40);
      }
  }

UKHeliBob

Code: [Select]

void tapLetter(int a, int b, int c)
{
  if (a <= 89)
  {
    for (posPan = 90; posPan <= a; posPan += 4)
    {


I have not been following this thread closely but the for loop above looks wrong

a is less than or equal to 89
posPan starts at 90 and while it is less than or equal to a the code block is executes and 4 added to posPan.  As posPan will not be less than or equal to a the for loop will never run
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

wildbill

What's happening here?
Code: [Select]

  byte b = 29;


You're trying to read memory in the movements array that's way outside its boundaries.

splext

Had my < and > and  + and - all jumbled! coding blindness from writing it at 1am no doubt!

Thanks HeliBob! resolved... for now!

and @wildbill, it is because once I am finished i will have 29 different key options to press. Am I using it incorrectly?

wildbill

it is because once I am finished i will have 29 different key options to press. Am I using it incorrectly?
Ok, but right now you don't have 29, so you're reading memory that isn't part of the array. If you made the same error and were writing on it, you can expect unpleasant results.

This is a good example of why it's inadvisable to use 'magic numbers' in your code. Consider making a const byte to store the 29 and use that in both the array definition and your letter1Select function.

Go Up