Running peristaltic pump with keypad input

Let me preface this with how much of an incredible novice at this i am. My profession is mechanical fitting and i would like to broaden my horizons! Coding is defiantly not a skill that comes naturally to me.

Let me firstly outline the aims of my project. The operator inputs on a keypad (https://tinyurl.com/y6twzxbr) either 1 or 2 displayed on a LCD(https://tinyurl.com/y9zt4x7o). The operator input triggers a program that runs a peristaltic pump(https://tinyurl.com/ybkm3ptd) on a given delay to deliver a known amount of liquid. I am using a Mega 2560 R3 with a linksprite motor shield v1.0b with the above components.

Now for my shameful attempt at coding.

#include <Keypad.h>
#include <UTFT.h>  // Arduino LCD library
#include <SPI.h>


//TFT 
UTFT myGLCD (ITDB18SP, 51, 50, 49, 48, 47);
extern uint8_t SmallFont[];
//TFT

// motor shield global constants start
int pinI1=8;//define I1 interface
int pinI2=11;//define I2 interface 
int speedpinA=9;//enable motor A
int pinI3=12;//define I3 interface 
int pinI4=13;//define I4 interface 
int speedpinB=10;//enable motor B
int spead =127;//define the spead of motor
int delayTime =0;// setting delay time to integer
// Motorshield stop
char userInput='0';

//keypad variable and initialization
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'0','1','2','3'},
  {'4','5','6','7'},
  {'8','9','A','B'},
  {'C','D','E','F'}
};
byte rowPins[ROWS] = {25, 24, 23, 22}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {29, 28, 27, 26}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad cKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 
//keypad STOP


void setup(){
  //MS 
  pinMode(pinI1,OUTPUT);
  pinMode(pinI2,OUTPUT);
  pinMode(speedpinA,OUTPUT);
  pinMode(pinI3,OUTPUT);
  pinMode(pinI4,OUTPUT);
  pinMode(speedpinB,OUTPUT);
  //MS 
  purge();
  myGLCD.InitLCD(LANDSCAPE);
  myGLCD.setFont(SmallFont);
  myGLCD.print("Please enter program to run (1 or 2)", CENTER, 1);
  char userInput = cKeypad.getKey(); // getting input that decides program to run
  delay(250);
  myGLCD.print(userInput, CENTER,12);
  Serial.begin(9600);
  
       }

void motor(){
  analogWrite(speedpinA,spead);//input a simulation value to set the speed
    digitalWrite(pinI2,LOW);//turn DC Motor A move anticlockwise
     digitalWrite(pinI1,HIGH);
     delay(delayTime);
     stop();


}

void purge(){
  analogWrite(speedpinA,spead);//input a simulation value to set the speed
    digitalWrite(pinI2,LOW);//turn DC Motor A move anticlockwise
     digitalWrite(pinI1,HIGH);
     delay(delayTime);
     stop();


}

void stop()//
{
     digitalWrite(speedpinA,LOW);// Unenable the pin, to stop the motor. this should be done to avoid damaging the motor. 
     digitalWrite(speedpinB,LOW);
      
}

void loop(){
  if (userInput == '1') {
    delayTime = 1000;    
    motor(); 
  }
    if (userInput == '2'){
      delayTime = 2000;
      motor();}
      
  Serial.print(userInput);
}

If someone could just point me to skills i can learn to complete this i would be appreciative.

Regards,

It looks like all you are missing is the code to read the keyboard - assuming your motor control stuff is good. getkey is the function you need & the example code for the library looks helpful: Arduino Playground - HomePage.

When you put " char userInput = cKeypad.getKey();" in setup() you created a local variable called userInput. This is a SEPARATE variable from the global variable that still contains '0'. When setup() ends the local 'userInput' disappears ("Goes out of scope."). Your loop() is only seeing the '0' in the global varaible named 'userInput'.

Take out that line and put this line at the top of loop():

 userInput = cKeypad.getKey();

If no key is pressed the returned value will be 0 (not the character '0', the integer value 0). When you press a key on the keypad it will be processed next time through loop().

Let me preface this…

A literate mechanical engineer who also writes reasonably good code. How intriguing.

What John has (correctly) said would make your code look like this,

#include <Keypad.h>
#include <UTFT.h>  // Arduino LCD library
#include <SPI.h>

//TFT
UTFT myGLCD (ITDB18SP, 51, 50, 49, 48, 47);
extern uint8_t SmallFont[];
//TFT

// motor shield global constants start
int pinI1=8;//define I1 interface
int pinI2=11;//define I2 interface
int speedpinA=9;//enable motor A
int pinI3=12;//define I3 interface
int pinI4=13;//define I4 interface
int speedpinB=10;//enable motor B
int spead =127;//define the spead of motor
int delayTime =0;// setting delay time to integer
// Motorshield stop
char userInput='0';

//keypad variable and initialization
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = 
{
    {'0','1','2','3'},
    {'4','5','6','7'},
    {'8','9','A','B'},
    {'C','D','E','F'}
};
byte rowPins[ROWS] = {25, 24, 23, 22}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {29, 28, 27, 26}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad cKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
//keypad STOP

void setup()
{
    //MS
    pinMode(pinI1,OUTPUT);
    pinMode(pinI2,OUTPUT);
    pinMode(speedpinA,OUTPUT);
    pinMode(pinI3,OUTPUT);
    pinMode(pinI4,OUTPUT);
    pinMode(speedpinB,OUTPUT);
    //MS
    purge();
    myGLCD.InitLCD(LANDSCAPE);
    myGLCD.setFont(SmallFont);
    myGLCD.print("Please enter program to run (1 or 2)", CENTER, 1);
    myGLCD.print(userInput, CENTER,12);
    Serial.begin(9600);
}

void motor()
{
    analogWrite(speedpinA,spead);//input a simulation value to set the speed
    digitalWrite(pinI2,LOW);//turn DC Motor A move anticlockwise
    digitalWrite(pinI1,HIGH);
    delay(delayTime);
    stop();
}

void purge()
{
    analogWrite(speedpinA,spead);//input a simulation value to set the speed
    digitalWrite(pinI2,LOW);//turn DC Motor A move anticlockwise
    digitalWrite(pinI1,HIGH);
    delay(delayTime);
    stop();
}

void stop()//
{
    digitalWrite(speedpinA,LOW);// Unenable the pin, to stop the motor. this should be done to avoid damaging the motor.
    digitalWrite(speedpinB,LOW);
}

void loop()
{
    userInput = cKeypad.getKey(); // getting input that decides program to run

    if (userInput == '1') 
    {
        delayTime = 1000;   
        motor();
    }
    if (userInput == '2')
    {
        delayTime = 2000;
        motor();
    }
    Serial.print(userInput);
}

The rest of your code looks fine. The only issue I have is that if userInput is neither 1 or 2, the loop is going to be zipping around at the speed of light trying to print whatever userInput happens to be. If all you want to know (print) is what the user has input, you could alter the print statement toif(userInput) Serial.print(userInput);as this would then only print non-zero inputs (0 failing the test).

@wildbill, thanks for the input

@johnwasser, thanks for the explanation.

@DKWatson, thanks for the kind words. It’s especially kind when i work in an industry where teeth and coherent sentences are not mandatory! j/k

With the adjustments the sketch worked as desired. In an effort to expand on this i have, with my limited coding ability tried to add some further functions. I would like to know if there are any simplifications or coding faux pas i have made, so i can neaten up my code.

#include <Keypad.h>
#include <UTFT.h>  // Arduino LCD library
#include <SPI.h>

//TFT
UTFT myGLCD (ITDB18SP, 51, 50, 49, 48, 47);
extern uint8_t SmallFont[];
//TFT

// motor shield global constants start
int pinI1 = 8; //define I1 interface
int pinI2 = 11; //define I2 interface
int speedpinA = 9; //enable motor A
int pinI3 = 12; //define I3 interface
int pinI4 = 13; //define I4 interface
int speedpinB = 10; //enable motor B
int spead = 127; //define the spead of motor
int delayTime = 0; // setting delay time to integer
// Motorshield stop
char userInput = '0';
byte liquidVolume = 0;

//keypad variable and initialization
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] =
{
  {'0', '1', '2', '3'},
  {'4', '5', '6', '7'},
  {'8', '9', 'A', 'B'},
  {'C', 'D', 'E', 'F'}
};
byte rowPins[ROWS] = {25, 24, 23, 22}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {29, 28, 27, 26}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad cKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
//keypad STOP

void setup()
{
  //MS
  pinMode(pinI1, OUTPUT);
  pinMode(pinI2, OUTPUT);
  pinMode(speedpinA, OUTPUT);
  pinMode(pinI3, OUTPUT);
  pinMode(pinI4, OUTPUT);
  pinMode(speedpinB, OUTPUT);
  //MS
  purge();
  myGLCD.InitLCD(LANDSCAPE);
  myGLCD.setFont(SmallFont);
  myGLCD.print("Please enter volume of liquid followed by the # key ", 0, 0);
  myGLCD.setColor(0, 0, 255);
  myGLCD.printNumI(liquidVolume , 132, 90, 0);
}


void motor()
{
  for (int i = 0; i == liquidVolume; i++) {
    analogWrite(speedpinA, spead); //input a simulation value to set the speed
    digitalWrite(pinI2, LOW); //turn DC Motor A move anticlockwise
    digitalWrite(pinI1, HIGH);
    delay(delayTime);
    stop();
  }
}

void purge()
{
  analogWrite(speedpinA, spead); //input a simulation value to set the speed
  digitalWrite(pinI2, LOW); //turn DC Motor A move anticlockwise
  digitalWrite(pinI1, HIGH);
  delay(5000);
  stop();
}

void stop()
{
  digitalWrite(speedpinA, LOW); // Unenable the pin, to stop the motor. this should be done to avoid damaging the motor.
  digitalWrite(speedpinB, LOW);
}


void loop() {
  char key = cKeypad.getKey();
  if (key != NO_KEY)
  {
    if ( (key >= '0') && (key <= '9') 
    {
      liquidVolume = liquidVolume * 10;
      liquidVolume = liquidVolume + key - '0';
    }
    if ( key == '#' )
    { myGLCD.clrScr();
      myGLCD.print("Please enter the desired program to run (1 or 2)", 0, 0);
      userInput = cKeypad.getKey(); // getting input that decides program to run

      if (userInput == '1')
      {
        delayTime = 1000;
        motor();
      }
      if (userInput == '2')
      {
        delayTime = 2000;
        motor();
      }
    }
  }
}

Also how the hell do i program a keypad on I2C i cannot find to much information about the nuts and bolts.

A literate mechanical engineer ...

Just wondering, have you ever met any illiterate mechanical or any other type of engineers ?

@Watcher, mechanical engineering is a diverse field ranging from designers to the plebs that twist bolts. Unfortunately i can in my experience say i have met people in my country with limited literacy verging on illiteracy that hold mechanical engineering certificates(non Bsc).

I'm surprised it works - I'd expect the get key you use to get the userInput variable to return NO_KEY unless you're very quick on the keyboard. waitforkey might be more appropriate there although that blocking behavior may be problematic as your sketch grows.

FYI…

      liquidVolume = liquidVolume * 10;
      liquidVolume = liquidVolume + key - '0';

Since this sort of thing is very common, C and C++ have shortcut operators:

      liquidVolume *= 10;
      liquidVolume += key - '0';

These save you the trouble of writing the variable name twice and make the code a little bit easier to read.

jstubbs:
@Watcher, mechanical engineering is a diverse field ranging from designers to the plebs that twist bolts. Unfortunately i can in my experience say i have met people in my country with limited literacy verging on illiteracy that hold mechanical engineering certificates(non Bsc).

Ok..in my book engineering means at least BSc -BEng