Arduino Uno working within an Interrupt

Hi all,

I would like send a signal in an interrupt when variableA on my analogRead is more than 300.
After variableB has reached a value above 300 on the analogRead, I want the digitalWrite to stop.

Example:

void Interrupt(){
if (variableA >300){
digitalWrite (variableD, HIGH);
// Now wait until variableB has reached a value above 300
digitalWrite (variableD, LOW);
}

and now what could I do according to you?
Many thanks,

Mathew

An analogRead takes 100us.
You don't want that sort of delay in an interrupt.

(That was a snippet of answer to match your snippet of code)

I realize I don't give much to work with, and I'm sorry for that. My background is machining, and nearly everything in Arduino takes tons of time for me to figure out or understand. I'm not worried about the long delay, unless you tell me that an Interrupt actually can not handle such a long delay I'd still like to try.
Is there a way?

I don't see why an interrupt is necessary or desirable, but then, I don't see any code or context either.

You are not going to get any useful advice unless you explain what you are trying to do. (It's a bit like asking somebody how to drive without saying which side of the road cars drive on, or even if it's a car or a bulldozer).

...R

Ok what I would like to do is drive 2 pneumatic cylinders.

I have four digital outputs that I use to drive four transistors that in turn drive two 5/2 valves.
The relays should not be driven for too long, so I would like to make it high, wait for a bit and make it low.
I have three NPN end switches that I've finally gotten to understand how they work.
I have a four position turning switch.
What I'd like to do with them I have written out
I have two 'home positions'.
The home positions are:
Cylinder A out and Cylinder B out. (Turn switch position 1)
and Cylinder A out and Cylinder B in. (Turn switch position 4)

I want to go one way:
Cylinder A in. (second switch position)
When he gets there
Cylinder B out. (third switch position)
When he gets there
Cylinder A out. (fourth switch position)

I want to go the other way:
Cylinder A in. (third switch position)
When he gets there
Cylinder B in. (second switch position)
When he gets there
Cylinder A out. (first switch position)

I thought I'd make good use of the RISING part of the Interrupt where he checks the analog inputs of the NPN switches on what should be signaled.

I think it is possible for me to buy an Arduino Mega if more interrupt pins are required. PLC's however are out of the question for me, at the moment.
If there is any more explaining needed, feel free to ask.
Mathew
Attached you may find a 'mechanical' way of what I thought I'd make but in an electrical way.

And the mantra I so often find it necessary to repeat - It is one of the most common misunderstandings for "newbies" to think that an interrupt is a means to alter the flow of the main program. In fact, the very opposite is the case, an interrupt is designed such that a brief but important operation which must and can be processed immediately will be performed without affecting the flow of the primary program in any way.

This is not to be confused with the consequence that something that the ISR does may later be consequential to the main program as it continues to process its various tasks. This is equally true of a multi-tasking OS where an interrupt may result in task-switching but nevertheless on resumption, the immediate course of each task is as a matter of definition, unaffected.


So ...

If you care to post your code using the "code" mark-up (the "[ # ]" button above the reply window), we will (most likely) be happy to explain the mistakes (such as using the "delay()" function in an actual application) you have made - in a constructive (believe it or not) fashion. :smiley:

These are mechanical moving things - do you really think you need interrupts, which operate in the realms of single digit microsecond intervals?
Hint: at the speed of sound, an object would move about 1mm in the time a reasonably quick interrupt could be serviced.

The code I have is mainly nonexistent, because I have no idea what I should do.

I would like to subroutine (that is a new word to me Just as ISR and snippet) in some way,I think.
I thought an Interrupt would do just fine, because I don't care about a void loop for my program. I thought I would just let the loop empty and get on with two Interrupts.
What I wanted to do is somewhat like the program below, which I wrote, but with the help of the NPN end switches that will check for me whether or not the cylinder is there instead of waiting milliseconds.

// Digitale pin 13 is sleetje achteruit
// Digitale pin 12 is sleetje vooruit
// Digitale pin 11 is cilinder achteruit
// Digitale pin 10 is cilinder vooruit
volatile int slach = 13;
volatile int slvoo = 12;
volatile int ciach = 11;
volatile int civoo = 10;

// Pin 2 is knop rechtsom
// pin 3 is knop linksom


void setup(){
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(13,OUTPUT);
  attachInterrupt(0, pak, RISING); //pin 2 is de pin voor interrupt0 op een Arduino UNO
  attachInterrupt(1, leg, RISING); //pin 3 is de pin voor interrupt1 op een Arduino UNO
  Serial.begin(9600);
  
  digitalWrite( slach, HIGH);
  digitalWrite( ciach, HIGH);
  delay(1000);
  digitalWrite( slach, LOW);
  digitalWrite( ciach, LOW);
  delay(500);
}
void loop(){
  
}
void pak(){
  Serial.println("Pakt op");
  digitalWrite( slvoo, HIGH);
  delay (500); 
  digitalWrite( slvoo, LOW);
  digitalWrite( civoo, HIGH);
  delay (500);
  digitalWrite( civoo, LOW);
  digitalWrite( slach, HIGH);
  delay (500);
  digitalWrite( slach, LOW);
}

void leg(){
  Serial.println("Legt weg");
  digitalWrite( slvoo, HIGH);
  delay (500); 
  digitalWrite( slvoo, LOW);
  digitalWrite( ciach, HIGH);
  delay (500);
  digitalWrite( ciach, LOW);
  digitalWrite( slach, HIGH);
  delay (500);
  digitalWrite( slach, LOW);
}

So again, please tell me, what would you have me do?
Because at the speed of sound having objects move for me doesn't sound like a reason not to do it.
Mathew

a) you shouldn't be using "delay()"
b) you really shouldn't be using "delay()" in interrupt context.
c) you really shouldn't be doing serial I/O in interrupt context.

Have a look at blink without delay, without delay.

volatile int slach = 13;
volatile int slvoo = 12;
volatile int ciach = 11;
volatile int civoo = 10;

"const" not "volatile"

your lucky i speak dutch, few questions
a 5/2 solenoid only has 1 coil, so maybe it is 5/3 (you can stop the movement somewhere in the middle.)
so you have two buttons one for pak and one for leg.
fine
the interupt is a good thought to use, and you did it almost correct (missing return from interupt .
Put in the interupt only a vlag on the interupt put the vlagpak high and return.
another for leg obvious
in the loop:{
if vlagpak { pak()}
if vlagleg {leg()}
}
at the end of a leg routine reset the vlagpak, this way you can not pak twice.

more info please go to arduinoforum.nl (as here it is crowdy or to shooter@home.nl

the interupt is a good thought to use,

With delay() and serial I/O?
No really not.

and you did it almost correct (missing return from interupt .

A what?
You're not returning from an interrupt, you're returning from a void function.

In Reply #5 you have described a series of end-points without considering how you get from one to the other, and how long it takes between the end-points.

If it was my project I would write down (pencil and paper or a text editor) ALL the steps that must happen -
switch something on
test to see if it has reached its destination
switch something else on
etc
etc.

As others have said it seems very unlikely that any interrupts will be needed. The trick is to organize your code so that loop() can check positions at a high enough frequency.

...R

Robin2:
The trick is to organise your code so that loop() can check positions at a high enough frequency.

Which is exactly what "loop()" is for.

Now, if you have something that takes a while to do - such as serial output - then that will take its time whether or not you have interrupts. You can do certain things in interrupts - such as taking a note (in milliseconds) of when they occurred - but that's about all you can do whilst output is occurring; you cannot start another substantial task.

If you need to do anything more complex, you need to be able to break it up into (much) smaller steps which can be performed "in between" other tasks in the loop using a "state machine" to keep track of which step is in progress at any given time. Serial input and output can be performed one character at a time using functions that determine whether a character or a buffer is available on a given pass through the loop, and passing on if it is not, but the more complex libraries are not written for this (cooperative multitasking).

Ok, the past few comments have been a bit helpful. I would however ask that AWOL never comment on this forum question again, because he or she is blunt and not helpful.

The valves are Bi-stable, meaning they do have two relays that switch them. The relays shouldn't be powered continuously. Switching them off after a short while is the way to go.

There are four stable positions for the switch and I thought I'd look at millisecond speed at the values for the NPN end switches, and control the relays according to the positions of both cylinders, but even so still have them only move at a user command by a switch like this.

and only in a certain way.
When switch to 2 FROM position 1 I need my cylinders do something entirely different from when I switch to position 2 FROM position 3.
I use the end switches as a fail-safe because I don't want wrong moves to be made because of a situation wherein a user switches too fast from one side to the other and the cylinders haven't made their full stroke.

I really don't know how I should put these rules in a loop.

Even as a thing about the steps that must happen.

Maybe
Loop{
Look if the switch is on 1
If it is make a state change to 1
If it already was 1 do nothing
If the state was changed to 1 go see if analogRead Y reads more than three hundred
If it does move cylinder A IN

Look if the switch is on 2
If it is make a state change to 2
If it already was 2 do nothing
If the state was changed to 2 FROM 1 go see if analogRead X reads more than three hundred
If it does move cylinder A OUT
If the state was changed to 2 FROM 3 go see if analogRead Y reads more than three hundred, go see if analog Read X reads more than three hundred
If they do move Cylinder B IN

Look if the switch is on 3
If it is make a state change to 3
If it already was 3 do nothing
If the state was changed to 3 FROM 4 go see if analogRead Z reads more than three hundred
if it does move cylinder A OUT
If the state was changed to 3 FROM 2 go see if analogRead Y reads more than three hundred, go see if analog Read X reads more than three hundred
If they do move Cylinder B OUT

Look if the switch is on 4
If it is make a state change to 4
If it already was 4 do nothing
If the state was changed from 3 to 4 go see if analogRead Z reads more than three hundred
If it does move Cylinder A IN
loop}
subroutines
Cylinder A in:
digitalWrite 13 HIGH
Delay 50 miliseconds
digitalWrite 13 LOW

Cylinder B in:
digitalWrite 11 HIGH
Delay 50 miliseconds
digitalWrite 11 LOW

Cylinder A out:
digitalWrite 12 HIGH
Delay 50 miliseconds
digitalWrite 12 LOW

Cylinder B out:
digitalWrite 10 HIGH
Delay 50 miliseconds
digitalWrite 10 LOW

Even this method would not be foolproof but I'd get somewhere I think I'd be able to pick up from.

would however ask that AWOL never comment on this forum question again, because he or she is blunt and not helpful.

Not gonna happen :wink:

I prefer "concise" to "blunt"

How can you say "unhelpful"?
I steered you away from an approach that couldn't possibly work, didn't I?
I corrected your misuse of "volatile", didn't I?

I believe the problem will be easier to solve if you separate the setting (or changing) of the states from the business of acting on the states. Your loop() function might look like this

void loop() {
   readSwitchAndSetCylinderGoals();
   moveCylindersToGoal();
}

and the function to move the cylinders would be something like this (bear in mind I haven't bothered with changing direction)

void moveCylindersToGoal() {
   for (n = 0; n < numCylinders; n++) {
      if (cylinderPos[n] < cylinderGoal[n]) { 
          moveCylinder(n);  // assumes there is a function to move a cylinder 1 step towards the goal
      }
   } 
}

This is the same concept as in the link I posted earlier.

...R

can you use fritzing?
make a nice schematic with all in/out with it.
i see you want to use these endswitches, be aware they need normally 24 volts and some resistors to be used on an arduino.
(you will have to try them with a simple voltmeter and a led.

now for the positions:
you have 4 positions:
in1/in2 in1/out2 out1/in2 out1/out2
lets assume
in1 means arm is in
in2 means gripper is closed.

end contacts:
on arm both in and out
on gripper only on out as when gripper is not closed fully because it has a can inside it will never be detecting gripper closed.

please do not start with this state diagram try it first getting all working.

you are having two routines which are fine.
one called pak and another called leg.
so you only need 2 positions of the switch either pak or leg, actually you only need 1 command either pak or leg
so one signal is enough so a simple toggle switch or one contact of the dekkenschakelaar is enough.

i would add two outputs ready with pak and ready with leg so you can tell other system you are ready with your sequence.

as you state the solenoids only need a small time, please have this time as a variable in the setup. start with 1000 msec. sand lower it down until the cylinder is not reacting anymore. probably around 200 msec

make some pictures what you are doing, or a youtube.
you may put it here (i have a subscription on this one.
or on arduinoforum.nl
and yes your program looked fine, oke i must admit interupt is a bit heavy but the thinking was good and valid.
make some serial.println in your program so you can monitor its behavior.
and just try try.
if you keep me posted i will stay and help you.
workemail is shooter@home.nl

i must admit interupt is a bit heavy but the thinking was good and valid.

No!
The thinking was most definitely not good - you're delusional if you think it could work, and you're doing the OP a disservice by misleading them.
Read it again.

awol i know you are good in arduino, the assignment they got, is in first instance: if you give a command lets do something in a sequence.
i realise interupt is a bit heavy on this, however The students do not realise the implications of a interupt yet, and most of them dont touch it, only 25% are looking at it and only 5% are trying, and 3% succeed in using interupts. It is a learning proces. I am sure your first attempt had same flaws, and i have to make them these faults, however also encourage them to try.
As you saw in the posts he is also touching state machines. Now i have to tell him, first make this assignment and make it work, as time is limited.
Some of them are really good in programming, most can google, and 1 has found a helpful forum.
I never shoot, i have patience, everybody has a different way to solve a problem. (btw solution is on mastercomputer under projects, it has only 10 lines) now wait until this student will dig in the master.
I love students and other people that really think,
and yes i like you too, sometimes a bit hard, however give it a little rest as most of them can sort out good, bad and ugly.
see you around