I have a project building a small parts counter. As it stands now I need the motor to reverse when it senses a jam. Coding this has me stumped. I have tried numerous times, but no luck. Your help will be much appreciated.
Project hardware:
Arduino MEGA 2560
Rotary Encoder KY-040
LMioEtool DC motor, reversible, 12v, 10 rpm
Chanzon 12v, 3A, 36W AC-Dc switching wall wart
L298N Motor drive controller, Dual H-bridge
5v Solid State Relay Module
4 x 4 Membrane Keypad.
16 x 2 Liquid Crystal Display.
Adafruit IR Break Beam Sensor (ADA2168))
Potentiometer (for LCD).
2 push buttons (one for external reset, one for cycle start.)
1 10k resistor (cycle start pushbutton)
1 LED (blue) mimics the onboard pin 13 LED.
1 220 ohm resistor (for blue LED)
1 capacitor 0.1uF-- (across LCD pins 1&2)
Project Goal:
LCD prompts user for input.
User enters a desired package quantity. (This quantity is stored until the Arduino Mega is reset.)
Motor turns on.
Parts pass thru the IR beam and are counted.
Motor stops when the desired quantity is reached.
If the motor stalls then reverse the motor for 1 second to clear the jam
Press “Cycle Start” button to begin again. The ‘cycle start’ button will begin the cycle over.
(I have an external ‘reset’ button that resets the program (entire board) when a new part is run or quantity changes.
It is connected to the Mega’s reset pin)
How it actually works:
LCD prompts for input.
The desired quantity is printed on LCD and stored in ‘value’.
Motor turns on.
Need to code the motor reverse feature for the motor.
Beam Break sensor operates somewhat correctly sensing parts and counting them. (It miscounts though. This is a mechanical issue.)
The motor turns off on the correct beam break.
The counter resets to zero.
The entered quantity remains until the “Reset” button is pressed.
Press the cycle start button. Green LED flashes
Count field on the LCD clears, the motor turns on
PROBLEMS:
Beam break sensor can operate out of cycle. It would be best if it could only read in cycle. The counter should not increment while the motor is not running. I haven’t figured this out yet.
#include <Keypad.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(22,23,24,25,26,27);//Mega pins RS,E,D4,D5,D6,D7
//KEYPAD***************
const byte ROWS=4;
const byte COLS=4;
char hexaKeys[ROWS][COLS]=//define the buttons of the keypad
{{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'0','0','0','D'} };//changed the * & # values to zero
byte rowPins[ROWS]={35,34,33,32};
byte colPins[COLS]={31,30,29,};//disabled the letter keys by leaving out #28
Keypad customKeypad=Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
int ledPin=13;//on board LED (mega)and an external blue LED pin
int sensorPin=4;//break beam sensor is pin 4-blinks blue LED pin 13
int sensorState=0,lastState=0;//variable for reading the sensor status
int BBcounter=0;//holds the number of beam breaks
int KPvalue=0;//holds the key press quantity desired
int cyclePin=2;//cycle start pushbutton
int cycleState=0;// current cyclePin state
int lastCycleState=0;// previous cyclePin state
//H-bridge-12VDC motor
int enA=10;
int in1=12;
int in2=11;
// Rotary Encoder Inputs
int CLK=14;
int DT=15;
int ledCCW=9;//LED indicates the rotary disc is moving CCW
int ledCW=8;//LED indicate the rotary disc is going CW
int ENcounter=0;//encoder count
int currentStateCLK;//the current CLK pin state
int previousStateCLK;//holds the previous CLK pin state
String encdir ="";//holds the encoder's current direction
//ENCODER DEBOUNCE CODE
long lastDebounce=0;//Variables to debounce Rotary Encoder
int delayDebounce=0.01;//debounce delay time
int PreviousCLK;//previous CLK pin state
int PreviousDT;//previous DT pin state
int displaycounter=0;//Store current encoder value
int oldENcounter=0;
int newENcounter=0;
void setup(){
//H-bridge
pinMode(enA,OUTPUT);
pinMode(in1,OUTPUT);
pinMode(in2,OUTPUT);
//motor initial state=LOW
digitalWrite(in1,LOW);
digitalWrite(in2,LOW);
analogWrite(enA, 255);//enables motor
pinMode(ledPin,OUTPUT);//initialize the onboard LED pin as an output:
pinMode(sensorPin,INPUT_PULLUP);//initialize the sensor pin as an input: HIGH by default. Must use pullup or 10k resistor
lcd.begin(16,2);//tells arduino which LCD is being used
pinMode(cyclePin,INPUT);//cyclePin is an input
//encoder
pinMode (CLK,INPUT);//Set encoder pins as inputs
pinMode (DT,INPUT);
pinMode (ledCW,OUTPUT);//Set directional LED pins as outputs
pinMode (ledCCW,OUTPUT);
Serial.begin (2000000);
previousStateCLK = digitalRead(CLK);// Read the initial state of inputCLK
}
void loop(){
// Debounce encoder
if ((millis()-lastDebounce)>delayDebounce)//If enough time has passed check the rotary encoder
{check_rotary();//Rotary Encoder check routine below
PreviousCLK=digitalRead(CLK);
PreviousDT=digitalRead(DT);
lastDebounce=millis();}//Set variable to current millis() timer
//KEYPAD - LCD
lcd.setCursor(0,0);
lcd.print("Enter Qty");//Prompt the user for input
char KPkey=customKeypad.getKey();
if(KPkey){
KPvalue=(KPvalue*10)+KPkey-48;//store the value of the keypress until Reset is pressed.
lcd.setCursor(10,0);//set the cursor
lcd.print(KPvalue); }//Print the "Enter Qty" (value)
if(KPkey){
digitalWrite(in1,HIGH);//turns motor on CW
digitalWrite(in2,LOW);}
// ENCODER
currentStateCLK = digitalRead(CLK);//Read the current state of input CLK
if (currentStateCLK != previousStateCLK){
if(!currentStateCLK){//If the input DT state is different than the input CLK state then the encoder is rotating counterclockwise
if (digitalRead(DT) != currentStateCLK){//I switched ++ to -- and -- to ++ in this section
ENcounter ++;//because the encoder runs CCW while the part disc runs CW
encdir ="CW";
digitalWrite(ledCW,LOW);// turns CW green LED on
digitalWrite(ledCCW,HIGH);
}else{// Encoder is rotating CCW (Rotary disc/motor is going CW, which is what I want to monitor)
ENcounter--;
encdir ="CCW";
digitalWrite(ledCW,HIGH);//turns CCW red LED on
digitalWrite(ledCCW,LOW);}
//ATTEMPT TO CONTROL JAMMING OR STALLING
if(encdir!="CW"){
digitalWrite(in1,LOW);//turns motor on CCW
digitalWrite(in2,HIGH);
delay(1000);
digitalWrite(in1,HIGH);//turns motor on CW
digitalWrite(in2,LOW);}
Serial.print(encdir);
Serial.print(" ");
Serial.println(ENcounter);}
previousStateCLK = currentStateCLK;//set previousStateCLK to the currentStateCLK
}
//SENSOR
sensorState = digitalRead(sensorPin);//read the state of the sensor
if (sensorState == LOW){//check if the sensor beam is broken, if it is, the sensorState is LOW
digitalWrite(ledPin, HIGH);}//turn LED on
else {digitalWrite(ledPin, LOW);}//turn LED off
if(sensorState && !lastState){}//do nothing
if (!sensorState && lastState){
BBcounter++;
lcd.setCursor(0,1);
lcd.print("Count:");
lcd.print(BBcounter);}//prints the current beam breaks
lastState=sensorState;
if(BBcounter!=KPvalue);{}//do nothing if value and counter do not match
if(BBcounter==KPvalue){//if counted parts (counter) == required parts (value)
digitalWrite(in1,LOW);//turn motor off
digitalWrite(in2,LOW);
BBcounter=0;//reset both counters (beam break, encoder)
ENcounter=0;}
//CYCLE START
cycleState=digitalRead(cyclePin);//read the cycleStart pin
if(cycleState!=lastCycleState){//compare cycleState to its previous state
if(cycleState==HIGH){//if the state changes to HIGH turn motor on
digitalWrite(in1,HIGH);//motor runs clockwise
digitalWrite(in2,LOW);
lcd.setCursor(6,1);
lcd.print(" ");}
else{}//if cycleState is LOW do nothing
delay(100);}//delay to avoid bouncing
lastCycleState=cycleState;}//save the current cyclestate as the lastcyclestate, for next time through the loop
//Check if Rotary Encoder has moved
void check_rotary(){
if((PreviousCLK == 0)&&(PreviousDT==1)){
if((digitalRead(CLK)==1)&&(digitalRead(DT)==0)){
displaycounter++;}
if((digitalRead(CLK)==1)&&(digitalRead(DT)==1)){
displaycounter--;}}
if((PreviousCLK==1)&&(PreviousDT==0)){
if((digitalRead(CLK)==0)&&(digitalRead(DT)==1)){
displaycounter++;}
if((digitalRead(CLK)==0)&&(digitalRead(DT)==0)){
displaycounter--;}}
if((PreviousCLK==1)&&(PreviousDT==1)){
if((digitalRead(CLK)==0)&&(digitalRead(DT)==1)){
displaycounter++;}
if((digitalRead(CLK)==0)&&(digitalRead(DT)==0)){
displaycounter--;}}
if((PreviousCLK==0)&&(PreviousDT==0)){
if((digitalRead(CLK)==1)&&(digitalRead(DT)==0)){
displaycounter++;}
if((digitalRead(CLK)==1)&&(digitalRead(DT)==1)){
displaycounter--;}}
}