[4]

Arduino Code Help

[3]
[10] Like what you see?
Click here to donate to this forum and upgrade your account!

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#1
Not sue if this is the correct forum but here goes. I'm hoping there are some Arduino guru's here.

I trying to setup a feed motor that uses the state of two IR sensors to control a relay to cycle a motor on and off. The intent is to give some head room in the feed system to keep the motor from turning on/off constantly. The sensors will be spaced apart, high and low. When the space between the two sensors is full (both beams broken) the motor is of. As the system feeds the the top beam will become unbroken but the motor stays off until the lower beam is unbroken. When both beams are unbroken then the motor turns on. As the feed tube fills the lower beam will become broken but the motor stays on until the feed tube is full (both beams broken) then the motor turns off.

I have a single sensor working but I'm struggling on how to incorporate the second sensor.

Code so far.

/*
Feeder
*/

#define LEDPIN 12 //Motor staus LED is on pin 12
#define RELAY2PIN 10 //Feeder relay is on pin 10

#define SENSOR2PIN 2 //Feeder IR Sensor2 is on pin 2
#define SENSOR3PIN 3 //Feeder IR Sensor3 is on pin 3

// variables will change:
int sensor2State = 0, lastState=0; // variable for reading the sensor2 status
int sensor3State = 0, lastState=0; // variable for reading the sensor3 status

void setup() {
// initialize the LED pin as an output:
pinMode(LEDPIN, OUTPUT);
// initialize the RELAY2PIN pin as an output:
pinMode(RELAY2PIN, OUTPUT);
// initialize the sensor2 pin as an input:
pinMode(SENSOR2PIN, INPUT);
// initialize the sensor3 pin as an input:
pinMode(SENSOR3PIN, INPUT);

digitalWrite(SENSOR2PIN, HIGH); // turn on the pullup
digitalWrite(SENSOR3PIN, HIGH); // turn on the pullup

}

void loop(){
// read the state of the sensor2 value:
sensorBF2State = digitalRead(SENSOR2PIN);
// read the state of the sensor3 value:
sensorBF3State = digitalRead(SENSOR3PIN);

// check if the sensor3 beam is broken
// if it is, the sensor3State is LOW:
if (sensor3State == LOW) {
// turn RELAY2PIN off:
digitalWrite(RELAY2PIN, LOW);

}
else {
// turn RELAY2PIN on:
digitalWrite(RELAY2PIN, HIGH);

}
 

Eddyde

Bronze
Registered
Joined
Oct 13, 2014
Messages
1,410
Likes
1,196
#2
I sounds like you could simply wire the two sensors in series, both would have to close to complete the circuit. You might even be able to hook them directly to a relay and do away with the Arduino, unless its needed for other functions.
 

jwmelvin

Active Member
Registered
Joined
Jan 11, 2018
Messages
120
Likes
85
#3
Define a state variable for the motor status. If the motor is off, then only turn it on if the low beam is high; then, when the motor is on, only turn it off if the high beam is low.

if (stateMotor == LOW) { // motor is not running
if (stateSensorLow == HIGH) {
digitalWrite(RELAY2PIN, HIGH); // only turn motor on when level drops below SensorLow
stateMotor = HIGH; // track motor state
}
}
else { // motor is running
if (stateSensorHigh == LOW) {
digitalWrite(RELAY2PIN, LOW); // only stop motor when level rises above SensorHigh
stateMotor = LOW; // track motor state
}

It's possible to compact:

if (stateMotor == LOW && stateSensorLow == HIGH) {
digitalWrite(RELAY2PIN, HIGH);
stateMotor = HIGH;
}
else if (stateMotor == HIGH && stateSensorHigh == LOW) {
digitalWrite(RELAY2PIN, LOW); // only stop motor when level rises above SensorHigh
stateMotor = LOW;
}
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#4
Jay,

jwmelvin's code is right on target. He responded as I was creating essentially the same code. What he created is a state machine with 2 states: MOTOR_ON and MOTOR_OFF. While in the MOTOR_OFF state you just want to check the lower beam. While in the MOTOR_ON state you just want to check the upper beam.

By the way the method to enable the pullup resistors is:
pinMode(SENSOR2PIN, INPUT_PULLUP);
pinMode(SENSOR3PIN, INPUT_PULLUP);

Glen
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#5
Thanks guys. It didn't occur to me to see it from the motor state. I will noodle this over tonight.

Old dog trying to learn just wish I had more time and brain cells to learn it better. I really love what you can do with these types of platforms but it is light years away from what I have spent my career doing.
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#6
My IR sensors did not arrive today so I will have to wait until tomorrow to try. I fiddled with the code and it compiles but I'm not sure the variable definitions are correct.

/*
Feeder
*/

#define RELAY2 10 //Feeder relay is on pin 10
#define SENSORLOW 2 //Feeder Low IR Sensor is on pin 2
#define SENSORHIGH 3 //Feeder High IR Sensor is on pin 3

// variables will change:
int stateMotor = 0; // variable for reading the motor status
int stateSensorLow = 0; // variable for reading the sensorLow status
int stateSensorHigh = 0; // variable for reading the sensorHigh status

void setup() {

pinMode(RELAY2, OUTPUT); // initialize the RELAY2 pin as an output:
pinMode(SENSORLOW, INPUT_PULLUP); // initialize the sensorLow pin as an input:
pinMode(SENSORHIGH, INPUT_PULLUP); // initialize the sensorHigh pin as an input:

digitalWrite(SENSORLOW, HIGH); // turn on the pullup
digitalWrite(SENSORHIGH, HIGH); // turn on the pullup
}

void loop(){
if (stateMotor == LOW && stateSensorLow == HIGH) {
digitalWrite(RELAY2, HIGH); // only turn motor on when level drops below SensorLow
stateMotor = HIGH;
}
else if (stateMotor == HIGH && stateSensorHigh == LOW) {
digitalWrite(RELAY2, LOW); // only stop motor when level rises above SensorHigh
stateMotor = LOW;
}
}
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#7
Good morning Jay,

You're pretty close. Your code doesn't need the stateSensorLow and stateSensorHigh variables. That operation is handled directly with digitalRead(SENSORLOW) and digitalRead(SENSORHIGH) function calls. You could actually eliminate the stateMotor variable as the motor's ON/OFF state is actually stored in the pin. However, I think this code is more clear. Usually a more complex state machine has its state variable in memory.

The code below should work assuming the sensor logic levels are correct.

There are coding style conventions regarding indented code that I've included. Not all coders agree, but this is typical. It's all about readability.

I'm glad to see members of this site getting involved with software. While it looks difficult, it's really not any more complicated than planning the process to make a part on a machine; it's just a different mind-set.

Glen

/*
Feeder
*/

#define RELAY2 10 //Feeder relay is on pin 10
#define SENSORLOW 2 //Feeder Low IR Sensor is on pin 2
#define SENSORHIGH 3 //Feeder High IR Sensor is on pin 3

// state variables
int stateMotor = 0;

void setup() {
pinMode(RELAY2, OUTPUT); // initialize the RELAY2 pin as an output:
pinMode(SENSORLOW, INPUT_PULLUP); // sensor Low with pullup enabled
pinMode(SENSORHIGH, INPUT_PULLUP); // sensor High with pullup enabled
}

void loop() {
if(stateMotor == LOW) {
if(digitalRead(SENSORLOW) == HIGH) { // turn on if Low sensor shows empty
digitalWrite(RELAY2, HIGH);
stateMotor = HIGH;
}
}
else {
if(digitalRead(SENSORHIGH == LOW) { // turn off if High sensor shows full
digitalWrite(RELAY2, LOW);
stateMotor = LOW;
}
}
}
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#8
Update: the indenting doesn't show up with this commenting system.
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#9
Good morning Jay,

You're pretty close. Your code doesn't need the stateSensorLow and stateSensorHigh variables. That operation is handled directly with digitalRead(SENSORLOW) and digitalRead(SENSORHIGH) function calls. You could actually eliminate the stateMotor variable as the motor's ON/OFF state is actually stored in the pin. However, I think this code is more clear. Usually a more complex state machine has its state variable in memory.

The code below should work assuming the sensor logic levels are correct.

There are coding style conventions regarding indented code that I've included. Not all coders agree, but this is typical. It's all about readability.

I'm glad to see members of this site getting involved with software. While it looks difficult, it's really not any more complicated than planning the process to make a part on a machine; it's just a different mind-set.

Glen
Thanks Glen. I'd love to know this stuff better. I find it fascinating but its learning another language. I do better if I can immerse myself.

I follow most of the code you have. I was getting definition errors without the sensor variables so that's why they were there. I'm still a little confused as to how the stateMotor variable is tied to the relay?
 

jwmelvin

Active Member
Registered
Joined
Jan 11, 2018
Messages
120
Likes
85
#10
I'm still a little confused as to how the stateMotor variable is tied to the relay?
Manually, in that when you change the relay state you also change the stateMotor variable. I believe it is also possible to do a read operation on the relay output pin but I wasn’t sure so didn’t suggest that.
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#11
Jay,

The variable stateMotor keeps track of whether the motor is On or Off. It doesn't directly control the relay. That's done with the digitalWrite(RELAY2, x) statement.

To make things a bit more clear, I'll rename stateMotor to be motorOn. motorOn is a boolean variable with the values true or false.

// state variable declaration
bool motorOn = false;

When the program comes out of reset, motorOn is false. At the start of each pass through the loop the program looks at the motorOn variable. If motorOn is false (motor is Off), it looks at the Lower Sensor. If it needs to turn on, the program sets motorOn to true and turns the relay On with digitalWrite(RELAY2, HIGH). If the motor doesn't need to turn on, the program skips over the "else" statement to the bottom then jumps back to the top of the loop. To get into the "else" statement, motorOn must be true (motor is On) where it looks at the Upper Sensor. If the motor needs to turn Off, motorOn is set false and the relay is turned off with digitalWrite(RELAY2, LOW). Then the program jumps back o the start of the loop to repeat the process.

Since the comment system doesn't allow tabs, in the code below, I used 4 spaces for each tab indentation

#define RELAY2 10 //Feeder relay is on pin 10
#define SENSORLOW 2 //Feeder Low IR Sensor is on pin 2
#define SENSORHIGH 3 //Feeder High IR Sensor is on pin 3

// state variable
bool motorOn = false;

void setup() {
pinMode(RELAY2, OUTPUT); // initialize the RELAY2 pin as an output:
pinMode(SENSORLOW, INPUT_PULLUP); // sensor Low with pullup enabled
pinMode(SENSORHIGH, INPUT_PULLUP); // sensor High with pullup enabled

// this statement was missing on the original programs
digitalWrite(RELAY2, LOW); // make sure the relay is Off after reset
}

void loop() {
if(motorOn == false) {
if(digitalRead(SENSORLOW) == HIGH) { // turn On if Low sensor shows empty
digitalWrite(RELAY2, HIGH);
motorOn = true;
}
}
else {
if(digitalRead(SENSORHIGH == LOW) { // turn off if High sensor shows full
digitalWrite(RELAY2, LOW);
motorOn = false;
}
}
}

I've been using Arduino Nanos. They are powerful and cheap (about $4 each). So far I've built a stepper motor controller to replace the gear train on my G4000 lathe for feeding. One of these days I'll finish the version that will be able to do to threading in metric and US. I also just finished a DRO for the cross slide. It uses a $10 Harbor Freight caliper. It calculates diameters directly simplifying my work. It's working great on my current project which involves tight tolerances for ball bearings.

Glen
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#12
Glen, thank you for the detailed explanation. That really helps and is much appreciated. Hopefully I will be able to give it a whirl tonight.

Your lathe projects sounds great. Do you have build threads on those?

I have often though about setting up a system on the cross slide to use a stepper motor and micro controller for constant surface speed turning. I fall short when it comes to the software.
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#13
FYI to anyone following this thread, the code above is missing a ")" at "if(digitalRead(SENSORHIGH == LOW) { // turn off if High sensor shows full"

It should be "if(digitalRead(SENSORHIGH) == LOW) { // turn off if High sensor shows full"
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#14
Good catch. That's typical of software when you don't compile it before showing it to the world.

The commenting system removes extra spaces too. It didn't show up as I was typing it.

Here's the build thread for one of the projects.
Stepper replaces G4000 gear train for feeding

I'll put another together for the DRO, but it's not all that creative. It's been done many times.

Glen
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#15
It works!

I setup the sensors on a breadboard and it worked as planned so I decided to try adding a second feeder to the code. I did that and wired another sensor system on the breadboard and nothing?? The IR sensors were acting like they were not being read. I have the sensors powered by a separate bench supply so I checked that. I could see the emitters glowing in my phone camera so it didn't make any sense.

Thinking maybe I some how damaged the sensors I pulled it all apart and setup the single sensor code that has a LED and serial read so I could verify the Arduino was reading the sensor on the serial monitor. I also added a voltage regulator to be sure I would get a clean full 5v. Everything was laid loose and by pointing together or apart all was all working. I was getting messages on the serial monitor and the LED goes on off. Great so I checked all the IR sensors to be sure they all worked.

Thinking maybe I previously had a bad connection somewhere else I remounted the IR sensor to the breadboard and tried to break the beam. Nothing??? It was at that point I realized that at first I had been using a small steel ruler to break the beam but had changed to a postit note folded several times. Sure enough the IR goes right through the paper. Who knew? Works fine with the steel ruler. UGH! an hour wasted.

So I put it all together and tried the dual feeder code. Success!!! After that I added an alarm for another process. So far so good. Now to package it.

Here is my final code. Not sure if it is the proper way to format the dual feeder and alarm but it works.

/*
dual_feeder_w_alarm
*/

#define ASENSOR 7 //alarm IR sensor is on pin 7
#define ALED 8 //alarm LED is on pin 8
#define ABUZZ 9 //alarm buzzer relay is on pin 10
#define RELAY1 10 //feeder1 relay is on pin 10
#define RELAY2 11 //feeder2 relay is on pin 11
#define SENSOR1LOW 2 //feeder1 Low IR Sensor is on pin 2
#define SENSOR1HIGH 3 //feeder1 High IR Sensor is on pin 3
#define SENSOR2LOW 4 //feeder2 Low IR Sensor is on pin 4
#define SENSOR2HIGH 5 //feeder2 High IR Sensor is on pin 5

// state variable
int asensorState = 0;
bool motor1On = false;
bool motor2On = false;

void setup() {
pinMode(ALED, OUTPUT); // initialize the ALED pin as an output:
pinMode(ABUZZ, OUTPUT); // initialize the ABUZZ pin as an output:
pinMode(ASENSOR, INPUT); // initialize the ASENSOR pin as an input:
pinMode(RELAY1, OUTPUT); // initialize the RELAY1 pin as an output:
pinMode(RELAY2, OUTPUT); // initialize the RELAY2 pin as an output:
pinMode(SENSOR1LOW, INPUT_PULLUP); // sensor1 Low with pullup enabled
pinMode(SENSOR1HIGH, INPUT_PULLUP); // sensor1 High with pullup enabled
pinMode(SENSOR2LOW, INPUT_PULLUP); // sensor2 Low with pullup enabled
pinMode(SENSOR2HIGH, INPUT_PULLUP); // sensor2 High with pullup enabled

digitalWrite(ASENSOR, HIGH); //turn on the pullup
digitalWrite(RELAY1, LOW); // make sure the relay is Off after reset
digitalWrite(RELAY2, LOW); // make sure the relay is Off after reset
}

void loop() {
if(motor1On == false) {
if(digitalRead(SENSOR1LOW) == HIGH) { // turn On if Low sensor shows empty
digitalWrite(RELAY1, HIGH);
motor1On = true;
}
}
else {
if(digitalRead(SENSOR1HIGH) == LOW) { // turn off if High sensor shows full
digitalWrite(RELAY1, LOW);
motor1On = false;
}
}

{
if(motor2On == false) {
if(digitalRead(SENSOR2LOW) == HIGH) { // turn On if Low sensor shows empty
digitalWrite(RELAY2, HIGH);
motor2On = true;
}
}
else {
if(digitalRead(SENSOR2HIGH) == LOW) { // turn off if High sensor shows full
digitalWrite(RELAY2, LOW);
motor2On = false;
}
}

{
asensorState = digitalRead(ASENSOR); // read the state of the ASENSOR value:

if (asensorState == LOW) { // check if the sensor beam is broken, if it is, the sensorState is LOW:
digitalWrite(ALED, LOW); // turn LED on:
digitalWrite(ABUZZ, LOW); // turn BUZZER on:
}
else {
digitalWrite(ALED, HIGH); // turn LED off:
digitalWrite(ABUZZ, HIGH); // turn BUZZER off:
}
}
}
}

My prototyping mess :grin:

20180816_205504.png
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#16
Jay,

Your prototype looks pretty good to me. That's not a mess, it's progress.

Glen
 

P. Waller

H-M Supporter - Sustaining Member
H-M Platinum Supporter ($50)
Joined
Mar 10, 2018
Messages
655
Likes
437
#17
I've been using Arduino Nanos. They are powerful and cheap (about $4 each). So far I've built a stepper motor controller to replace the gear train on my G4000 lathe for feeding. One of these days I'll finish the version that will be able to do to threading in metric and US. I also just finished a DRO for the cross slide. It uses a $10 Harbor Freight caliper. It calculates diameters directly simplifying my work. It's working great on my current project which involves tight tolerances for ball bearings.

Glen
How would you incorporate the lathe C axis for threading?

I bought an Arduino Mega 2560 awhile ago, plugged it into a desktop once to see what it would do and it was not what I was looking for.
You can have it for the USPS cost from NJ. Of course this may be old tech by now. It does no good sitting on my desk so its next destination is the scrap.
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#18
Mr. Waller,

Thanks for the offer, but I've already got an Arduino Mega 2560. It's got the same CPU as the Nano, but it's got a lot more Input/Output, Flash and RAM.

Don't scrap the Mega. Just plugging it into your computer doesn't demonstrate much. Once you've made up your mind that you want to "electronify" some of your machinery you will find that it's just the thing you need. There are a couple of things you need to make the Mega useful: an LCD display (I'd recommend a 16 character by 2 rows or 20 character by 4 rows with the I2C 2 wire interface (about $5 to $12 each) and a 4x4 keypad (about $2 each). With these two extras you can build just about anything. Software isn't for everyone, but I find it fascinating.

Threading is pretty straightforward. I have to change my current 24 slot tachometer wheel to 64 slots plus a Top Dead Center indicator. The stepper will synchronize to TDC and adjust it's speed on each tick of the tachometer sensor. The stepper system already has an electronic stop and in knows where "Home Position" is (just before the start of the thread) so it can return there after each pass. The speed of the stepper is a simple ratio calculation based on the spindle speed and the desired pitch. I will be able to produce right and left threads in any pitch either US or metric or any oddball thread in between.

This threading mechanism will be still a manual process. I just won't have to mess around with the gear train.

Glen
 

P. Waller

H-M Supporter - Sustaining Member
H-M Platinum Supporter ($50)
Joined
Mar 10, 2018
Messages
655
Likes
437
#19
Mr. Waller,

Thanks for the offer, but I've already got an Arduino Mega 2560. It's got the same CPU as the Nano, but it's got a lot more Input/Output, Flash and RAM.

Don't scrap the Mega. Just plugging it into your computer doesn't demonstrate much. Once you've made up your mind that you want to "electronify" some of your machinery you will find that it's just the thing you need. There are a couple of things you need to make the Mega useful: an LCD display (I'd recommend a 16 character by 2 rows or 20 character by 4 rows with the I2C 2 wire interface (about $5 to $12 each) and a 4x4 keypad (about $2 each). With these two extras you can build just about anything. Software isn't for everyone, but I find it fascinating.

Threading is pretty straightforward. I have to change my current 24 slot tachometer wheel to 64 slots plus a Top Dead Center indicator. The stepper will synchronize to TDC and adjust it's speed on each tick of the tachometer sensor. The stepper system already has an electronic stop and in knows where "Home Position" is (just before the start of the thread) so it can return there after each pass. The speed of the stepper is a simple ratio calculation based on the spindle speed and the desired pitch. I will be able to produce right and left threads in any pitch either US or metric or any oddball thread in between.

This threading mechanism will be still a manual process. I just won't have to mess around with the gear train.

Glen
I understand how it works, I program and run CNC lathes for a living.
The application that I looked at the Arduino controller for is unrelated to machine tool control, ended up using a Mitsubishi PLC which works flawlessly and the programming is easily changed, it has no other HMI then START, STOP and several OH SH!* stops (-:

Also cost was not an issue.
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#20
I have everything almost working perfectly. The last problem is that when the system fills up to the lower break beam sensor, the next part that passes the upper sensor it is enough to trigger the sensor and stop the motor so the buffer zone never fills up to the upper sensor. I suspect if two parts fell at the right interval it could create a timing problem with the lower sensor as well. I need a way to have the sensors not trigger until the the beams have been broken for a time longer than for a part to pass by. I was looking at the milis function as a delay for the sensors but am having trouble seeing how to integrate it. I'm not even sure that is the best way to go.

Here is my current code.

/*
Feeder
*/

#define ASENSOR 7 //alarm IR sensor is on pin 7
#define ALED 8 //alarm LED is on pin 8
#define ABUZZ 9 //alarm buzzer relay is on pin 10
#define RELAY1 10 //feeder1 relay is on pin 10
#define RELAY2 11 //feeder2 relay is on pin 11
#define SENSOR1LOW 2 //feeder1 Low IR Sensor is on pin 2
#define SENSOR1HIGH 3 //feeder1 High IR Sensor is on pin 3
#define SENSOR2LOW 4 //feeder2 Low IR Sensor is on pin 4
#define SENSOR2HIGH 5 //feeder2 High IR Sensor is on pin 5

// state variable
int asensorState = 0;
bool motor1On = false;
bool motor2On = false;

void setup() {
pinMode(ALED, OUTPUT); // initialize the ALED pin as an output:
pinMode(ABUZZ, OUTPUT); // initialize the ABUZZ pin as an output:
pinMode(ASENSOR, INPUT); // initialize the ASENSOR pin as an input:
pinMode(RELAY1, OUTPUT); // initialize the RELAY1 pin as an output:
pinMode(RELAY2, OUTPUT); // initialize the RELAY2 pin as an output:
pinMode(SENSOR1LOW, INPUT_PULLUP); // sensor1 Low with pullup enabled
pinMode(SENSOR1HIGH, INPUT_PULLUP); // sensor1 High with pullup enabled
pinMode(SENSOR2LOW, INPUT_PULLUP); // sensor2 Low with pullup enabled
pinMode(SENSOR2HIGH, INPUT_PULLUP); // sensor2 High with pullup enabled

digitalWrite(ASENSOR, HIGH); //turn on the pullup
digitalWrite(RELAY1, HIGH); // make sure the relay is Off after reset
digitalWrite(RELAY2, HIGH); // make sure the relay is Off after reset
}

void loop() {
if(motor1On == false) {
if(digitalRead(SENSOR1LOW) == HIGH) { // turn On if Low sensor shows empty
digitalWrite(RELAY1, LOW);
motor1On = true;
}
}
else {
if(digitalRead(SENSOR1HIGH) == LOW) { // turn off if High sensor shows full
digitalWrite(RELAY1, HIGH);
motor1On = false;
}
}

{
if(motor2On == false) {
if(digitalRead(SENSOR2LOW) == HIGH) { // turn On if Low sensor shows empty
digitalWrite(RELAY2, LOW);
motor2On = true;
}
}
else {
if(digitalRead(SENSOR2HIGH) == LOW) { // turn off if High sensor shows full
digitalWrite(RELAY2, HIGH);
motor2On = false;
}
}

{
asensorState = digitalRead(ASENSOR); // read the state of the ASENSOR value:

if (asensorState == LOW) { // check if the sensor beam is broken, if it is, the sensorState is LOW:
digitalWrite(ALED, LOW); // turn LED on:
digitalWrite(ABUZZ, LOW); // turn BUZZER on:
}
else {
digitalWrite(ALED, HIGH); // turn LED off:
digitalWrite(ABUZZ, HIGH); // turn BUZZER off:
}
}
}
}
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#21
Jay,
I assumed you had a liquid that your were measuring. Your thinking is on the right track.

If you have objects falling through both beams, the code needs to integrate the samples to ignore the objects that are just passing through. Generally, it's not a good idea to use the millis() function in the main loop as it causes the code to stop until the time delay is completed. However, in this case I think it will be OK. Here's a simple implementation.

if(digitalRead(SENSOR1HIGH) == LOW) { // a part is detected in the beam
millis(xxx); // wait enough milliseconds to let the part fall through
if(digitalRead(SENSOR1HIGH) == LOW) { // look again to see if the beam is still broken
digitalWrite(RELAY1, HIGH);
motor1On = false;
}
}

What's going on here: when you detect an object in the beam, wait long enough to let it fall through then look again. If it's still there then turn the motor off. Otherwise ignore it.

Glen
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#22
Glen,
In my limited understanding I don't think millis() can be used this way? From what I have read isn't millis() used to compare time of the sensor state?

I though we didn't want to use a simple delay function as it pauses the code and the other sensors may miss events?

I have been looking at this example of millis() which I think is what I'm looking for but it is based on a button press and release so it gets confusing to me on how to use that when comparing the state of two sensors.

When I use the code example you provided I get this error.

Arduino: 1.8.5 (Windows 10), Board: "Arduino Nano, ATmega328P"

F:\1-Jay\Arduino\Progressive Press Control\Feeder2\Feeder_Alarm_Rev2\Feeder_Alarm_Rev2.ino: In function 'void loop()':

Feeder_Alarm_Rev2:45: error: too many arguments to function 'long unsigned int millis()'

millis(100);// Ignore passing object

^

In file included from sketch\Feeder_Alarm_Rev2.ino.cpp:1:0:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:140:15: note: declared here

unsigned long millis(void);

^

Feeder_Alarm_Rev2:61: error: too many arguments to function 'long unsigned int millis()'

millis(100);// Ignore passing object

^

In file included from sketch\Feeder_Alarm_Rev2.ino.cpp:1:0:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:140:15: note: declared here

unsigned long millis(void);

^

Feeder_Alarm_Rev2:81: error: expected '}' at end of input

}

^

Feeder_Alarm_Rev2:81: error: expected '}' at end of input

exit status 1
too many arguments to function 'long unsigned int millis()'
 

jwmelvin

Active Member
Registered
Joined
Jan 11, 2018
Messages
120
Likes
85
#23
millis() simply returns the current timer value.
It is definitely best to avoid using the delay() function as it will bite you eventually.

What you want to do is debounce a signal. You don't want to detect intermittent changes, only stable changes, as defined by remaining in a state for a certain time period (for you, longer than the time it takes an object to pass through the beam). While you can use a number of methods including a timer that measures from the initial change using the millis() function, I recommend using a library that is already made for this. I use it every time I want a button input to my system, because mechanical buttons have bounce in their electrical contacts.

I rewrote your code to take advantage of the Bounce2 library. Let me know if it makes sense to you.
 

Attachments

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#24
jwmelvin,

I ran your code and the motors do not turn on.

I'm curious why motor1On / sensor1 is duplicated? Should the second occurrence be motor2On / sensor2?

void loop() {
sensorsUpdate();
if (motor1On == false) { // motor is stopped
if (sensor1low.rose()) { // low sensor empty
startFeeder1();
}
}
else { // motor is running
if (sensor1high.fell()) { // high sensor full
stopFeeder1();
}
}
if (motor1On == false) { // motor is stopped
if (sensor1low.rose()) { // low sensor empty
startFeeder1();
}
}
else { // motor is running
if (sensor1high.fell()) { // high sensor full
stopFeeder1();
}
 

jwmelvin

Active Member
Registered
Joined
Jan 11, 2018
Messages
120
Likes
85
#25
Yes, of course, sorry about that. The bold names should have a 2 in them.

That won't, however, explain the issue with the motors not turning on. You did copy the Bounce2 library to the correct location and it shows up in your Arduino environment?

If it were me, I'd make a simple test program to debug the issue and make sure I am reading the sensors correctly.
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#26
I changed the other lines to have 2 in them but as you say that does not fix the issue. I downloaded the bounce2 zip file from github and used Add Zip. Library to install it. It sows up in the library and the code compiles so I'm assuming it is installed correctly.

Ha ha set up a simple test program he says..... I'll see what I can do.
 

gzoerner

Active Member
Registered
Joined
Apr 20, 2016
Messages
48
Likes
63
#27
Jay,

Sorry for the wrong code earlier. I'm away from my Arduino development PC on a road trip. If you substitute "delay(xxx)" for "millis(xxx) in the code that I sent earlier and you should be OK. Mr. Melvin is correct regarding millis(). It simply returns the number of milliseconds since the system was reset. delay(xxx) is the proper function. It delays the code for the number of milliseconds you specify.

Glen
 

stupoty

Active User
H-M Supporter - Gold Member ($25)
Joined
Dec 2, 2012
Messages
983
Likes
232
#28
H
Not sue if this is the correct forum but here goes. I'm hoping there are some Arduino guru's here.

I trying to setup a feed motor that uses the state of two IR sensors to control a relay to cycle a motor on and off. The intent is to give some head room in the feed system to keep the motor from turning on/off constantly. The sensors will be spaced apart, high and low. When the space between the two sensors is full (both beams broken) the motor is of. As the system feeds the the top beam will become unbroken but the motor stays off until the lower beam is unbroken. When both beams are unbroken then the motor turns on. As the feed tube fills the lower beam will become broken but the motor stays on until the feed tube is full (both beams broken) then the motor turns off.

I have a single sensor working but I'm struggling on how to incorporate the second sensor.

Code so far.

/*
Feeder
*/

#define LEDPIN 12 //Motor staus LED is on pin 12
#define RELAY2PIN 10 //Feeder relay is on pin 10

#define SENSOR2PIN 2 //Feeder IR Sensor2 is on pin 2
#define SENSOR3PIN 3 //Feeder IR Sensor3 is on pin 3

// variables will change:
int sensor2State = 0, lastState=0; // variable for reading the sensor2 status
int sensor3State = 0, lastState=0; // variable for reading the sensor3 status

void setup() {
// initialize the LED pin as an output:
pinMode(LEDPIN, OUTPUT);
// initialize the RELAY2PIN pin as an output:
pinMode(RELAY2PIN, OUTPUT);
// initialize the sensor2 pin as an input:
pinMode(SENSOR2PIN, INPUT);
// initialize the sensor3 pin as an input:
pinMode(SENSOR3PIN, INPUT);

digitalWrite(SENSOR2PIN, HIGH); // turn on the pullup
digitalWrite(SENSOR3PIN, HIGH); // turn on the pullup

}

void loop(){
// read the state of the sensor2 value:
sensorBF2State = digitalRead(SENSOR2PIN);
// read the state of the sensor3 value:
sensorBF3State = digitalRead(SENSOR3PIN);

// check if the sensor3 beam is broken
// if it is, the sensor3State is LOW:
if (sensor3State == LOW) {
// turn RELAY2PIN off:
digitalWrite(RELAY2PIN, LOW);

}
else {
// turn RELAY2PIN on:
digitalWrite(RELAY2PIN, HIGH);

}
ears a link to a timmer interupt tutorial.

https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers

Stu
 

jbolt

Active User
H-M Platinum Supporter ($50)
Joined
Dec 3, 2013
Messages
1,485
Likes
1,433
#29
jwmelvin,
On the machine using your code the relay pin is not being pulled to ground (turn on relay) regardless of the sensor conditions. I setup a single sensor array and relay on a breadboard and I get the opposite result with the relay being pulled to ground regardless of the sensor conditions. I'll try adding the second sensor/relay to the breadboard later and see what happens.

Glen,
I changed the code to add the delay to the upper sensor for both motors. Motor2 motor cycles on/off properly with the sensor2 conditions. However motor1 cycles on/off by the the upper sensor only and does not wait for the lower sensor to be empty? Without the delay both motors behave properly with the sensor conditions (except for the part dropping by).

I renamed the sensors because the HIGH/LOW was getting confusing.

/*
Feeder
*/

#define ASENSOR 7 //alarm IR sensor is on pin 7
#define ALED 8 //alarm LED is on pin 8
#define ABUZZ 9 //alarm buzzer relay is on pin 10
#define RELAY1 10 //feeder1 relay is on pin 10
#define RELAY2 11 //feeder2 relay is on pin 11
#define SENSOR1BOTTOM 2 //feeder1 Bottom IR Sensor is on pin 2
#define SENSOR1TOP 3 //feeder1 Top IR Sensor is on pin 3
#define SENSOR2BOTTOM 4 //feeder2 Bottom IR Sensor is on pin 4
#define SENSOR2TOP 5 //feeder2 Top IR Sensor is on pin 5

// state variable
int asensorState = 0;
bool motor1On = false;
bool motor2On = false;

void setup() {
pinMode(ALED, OUTPUT); // initialize the ALED pin as an output:
pinMode(ABUZZ, OUTPUT); // initialize the ABUZZ pin as an output:
pinMode(ASENSOR, INPUT); // initialize the ASENSOR pin as an input:
pinMode(RELAY1, OUTPUT); // initialize the RELAY1 pin as an output:
pinMode(RELAY2, OUTPUT); // initialize the RELAY2 pin as an output:
pinMode(SENSOR1BOTTOM, INPUT_PULLUP); // sensor1 bottom with pullup enabled
pinMode(SENSOR1TOP, INPUT_PULLUP); // sensor1 top with pullup enabled
pinMode(SENSOR2BOTTOM, INPUT_PULLUP); // sensor2 bottom with pullup enabled
pinMode(SENSOR2TOP, INPUT_PULLUP); // sensor2 top with pullup enabled

digitalWrite(ASENSOR, HIGH); //turn on the pullup
digitalWrite(RELAY1, HIGH); // make sure the relay is Off after reset
digitalWrite(RELAY2, HIGH); // make sure the relay is Off after reset
}

void loop() {
if(motor1On == false) {
if(digitalRead(SENSOR1BOTTOM) == HIGH) { // turn On if bottom sensor shows empty
digitalWrite(RELAY1, LOW);
motor1On = true;
}
}
else {
if(digitalRead(SENSOR1TOP) == LOW) { // check sensor
delay(250); // ingnore passing by sensor
if(digitalRead(SENSOR1TOP) == LOW) { // turn off if top sensor shows full
digitalWrite(RELAY1, HIGH);
motor1On = false;
}
}
}

{
if(motor2On == false) {
if(digitalRead(SENSOR2BOTTOM) == HIGH) { // turn On if bottom sensor shows empty
digitalWrite(RELAY2, LOW);
motor2On = true;
}
}
else {
if(digitalRead(SENSOR2TOP) == LOW) { // check sensor
delay(250); //ingore part passing by sensor
if(digitalRead(SENSOR2TOP) == LOW) { // turn off if top sensor shows full
digitalWrite(RELAY2, HIGH);
motor2On = false;
}
}
}

{
asensorState = digitalRead(ASENSOR); // read the state of the ASENSOR value:

if (asensorState == LOW) { // check if the sensor beam is broken, if it is, the sensorState is LOW:
digitalWrite(ALED, LOW); // turn LED on:
digitalWrite(ABUZZ, LOW); // turn BUZZER on:
}
else {
digitalWrite(ALED, HIGH); // turn LED off:
digitalWrite(ABUZZ, HIGH); // turn BUZZER off:
}
}
}
}
 

jwmelvin

Active Member
Registered
Joined
Jan 11, 2018
Messages
120
Likes
85
#30
jwmelvin,
On the machine using your code the relay pin is not being pulled to ground (turn on relay) regardless of the sensor conditions. I setup a single sensor array and relay on a breadboard and I get the opposite result with the relay being pulled to ground regardless of the sensor conditions. I'll try adding the second sensor/relay to the breadboard later and see what happens.
I was thinking of something a lot simpler. Like a sensor and a print statement. Try to get bounce working with a sensor so you are comfortable with it. Then build from there. It’s worth it.

Did you try a shorter delay for bounce like 50 ms?

I really urge you not to use delay() as a way of achieving what you want. If you can’t get bounce working I can help you do it another way. But I stopped doing things the hard way once I found bounce.
 
[6]
[5] [7]
Top