Interrupt from switch case/variable instead of pin

Hi all,

I am trying to run a program that has a voltmeter in it, which constantly checks if the voltage is in 3 given zones (0-1.9, 2-3, 3-5V) and then do something simple different for each zone.

I am running the voltmeter reading off of an analog pin (A0) and using a switch case to define the zones.

I figured an interrupt would be the best way to constantly check voltage but as far as I've seen you can only attach interrupts to pins so I am now stuck.

Thanks in advance,

I think you figured wrong, because an interrupt cannot be fired "constantly". If you change your aim from "constantly check" to check voltage in defined intervals, you could use a timer interrupt.

I don't see a much sense in the "interrupt from variable". Please clarify your idea.

depending on your hardware you can get an interrupt triggered on the ADC based on a threshold value but it's only one threshold, here you have 3 zones to monitor

if you don't think this is manageable from the loop, then use a timer to trigger the check from time to time, as an interrupt.

But it would be interesting to know why this can't be managed from the loop, which should run fast...

side note: to be more effective in your zone comparison, don't convert the analogRead into a voltage and perform floating point comparisons with 1.9, 2.0 and 3.0 - just use the integer you got from analogRead to define the intervals. It will be faster.

I didn't want to run this in the loop because I am running a stepper motor that reads inputs from the serial monitor and then checks with it's current position to move to the given position, as long as the voltage is in the right range. But as far as I am aware the loop will complete the stepper move and then check the voltage, which isn't useful.

to respond to your side note, that is what I was doing, I just hadn't explained it to save myself writing that out.

My bad, I had worded it poorly. I will explain a bit more: The three voltage zones will move a stepper motor forwards (0-1.9V), do nothing (2-3V) or move backwards (3.1-5V), so only the outer 2 zones are actually important. This will stop the rest of the code and continue moving in either direction until the voltage is in the correct range (2-3V).

I hope this clears things up

if you use accelStepper for example, the move is asynchronous. when you call stepper.run(), a step is taken if one needs to be taken, and you can perform other tests like reading the voltage and decide to issue a stop command or move the other way. Just make sure you don't block the loop for a long time

I wasn't using accelStepper, but I am now having a look at it, Thanks

here is a crude example

#include <AccelStepper.h>
const byte dirPin = 4;
const byte stepPin = 5;
const byte potPin = A0;

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);
long speed = 100;
long direction = 1;

void checkPot() {
  int potValue = analogRead(potPin);
  int newDirection = direction;
  if (potValue < 340) newDirection = -1;
  else if (potValue < 680) newDirection = 0;
  else  newDirection = 1;
  if (newDirection != direction) {
    direction = newDirection;
    Serial.print("New speed = "); Serial.println(direction * speed);
    stepper.setSpeed(direction * speed);
  }
}

void checkSerialForSpeed() {
  static long newSpeed = 0;
  int r = Serial.read();
  switch (r) {
    case '0'...'9':
      newSpeed = newSpeed * 10 + r - '0';
      break;

    case '\n':
      speed = newSpeed;
      newSpeed = 0;
      Serial.print("New speed = "); Serial.println(direction * speed);
      stepper.setSpeed(direction * speed);
      break;

    default: break; // ignore anything else
  }
}

void setup() {
  stepper.setMaxSpeed(10000);
  Serial.begin(115200);
  Serial.println("Ready");
}

void loop() {
  checkPot();
  checkSerialForSpeed();
  stepper.runSpeed();
}

the pot has 3 zones to set the direction of the stepper (left to go CCW, center to stop, right to go CW)
the Serial input is monitored (crudely, no error checking) for a new speed entry. type 200Return and the absolute steps per second will be set to that (multiplied by the direction imposed by the potentiometer).

to perform a better Serial input handling, I would suggest to study Serial Input Basics and use strtol() to parse the input and extract the speed with error checking.

Depending on how fast you want the stepping and voltage sampling, I’d expect you can get upwards of 100,000 voltage tests per second.

Your limits will be the A/D conversion time, the stepper pulse rate for speed.
In a well designed system, I’d hope you could double that initial estimate to 200k samples per second by using alternating A/D converters, and tight stepper code.

How fast do you need the voltage measurements ?
Is anything else going on ?

I need voltage readings every 200ms (5hz).
In case more detail is needed, I am making an EDM CNC machine (break metal with electric sparks at high precision). Voltage reading is to check if the cutting head is too close/correct distance/too far and then adjust accordingly

Have a look at my example
The reading is definitely > 5Hz without using any interrupts

Nice.

I'm unable to at this moment, but it would be easy fun to make the slide fader control the speed as well as the direction of the stepper.

With a dead zone in the middle for certainly stopped.

Gotta love wokwi.

a7

Which arduino are you using? Although you clearly do not need an interrupt for a 5Hz reading, depending on the processor you are using it is possible to start an analog conversion in the A/D, then have an interrupt generated on completion, as well as do a non-blocking reading by starting an A/D conversion, then checking the processor register for the bit that indicates A/D completion. Here is a very thorough reference to the A/D converter: http://www.gammon.com.au/adc

sure a simple map would do and then you apply the dead zone

speed = map(analogRead(A0), 0, 1023, -1000, 1000); // CCW to CW
if (speed > -100 && speed < 100) speed = 0; // dead zone

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.