Go Down

Topic: Interrupt help (Read 339 times) previous topic - next topic

Jonarotz

I am using a blue tooth switch and I want to terminate the switch at a given pulse. I have tried using pulseIn() and a duration, but it slowed the process down too much when it was waiting for the pulse. So naturally an interrupt would be a better choice.
I have written this code and it uses an interrupt, but it seems to be just as slow. Please don't beat me up too bad if this code looks like garbage...I am still trying to learn.

Code: [Select]

#include <SoftwareSerial.h>
 
SoftwareSerial bluetooth(10, 11); // RX, TX
int start = 5;  //PIN 5, OUTPUT
int TachPulse = 3; //Tach pulse input on Pin3
volatile unsigned int pulse;
boolean StartState = HIGH;
String receivedBluetoothString = "";


void setup() {
  Serial.begin(115200);
  bluetooth.begin(9600);
  pinMode(start, OUTPUT);
  pinMode(TachPulse, INPUT);
  attachInterrupt(1, count_pulse, RISING); //1=pin 3, count_pulse=interrupt function, RISING=edge to start interrupt
 }
 
void loop() {

    noInterrupts();
         
    if (bluetooth.available() > 0){
 
    char receivedBluetoothChar = bluetooth.read();
    receivedBluetoothString += receivedBluetoothChar;
 
    if (receivedBluetoothChar == '\n') {
                   
      if (receivedBluetoothString.toInt() == 887426){
         digitalWrite(start, (StartState) ? HIGH : LOW);
         StartState = !StartState;
      }
         
    receivedBluetoothString = "";
   
    }
   
    }

    pulse = 0; // For resetting count, otherwise pulse increments
    interrupts(); //Interrupts = count_pulse (pulse++)
    delay(1000);  //1 second delay, to pick up pulse
   
    Serial.print("Pulses per second: "); //Prints pulses to serial monitor
    Serial.println(pulse);
}   

void count_pulse() //This defines what the interrupt does
{
  pulse++;
    if (digitalRead(pulse > 10)){
        digitalWrite(start, LOW);
    }

}

Robin2

#1
Mar 20, 2017, 11:10 pm Last Edit: Mar 20, 2017, 11:10 pm by Robin2
I am using a blue tooth switch and I want to terminate the switch at a given pulse.
I don't understand that.
  • Is the Bluetooth device providing the pulse?
  • If not, what is providing the pulse?
  • What do you mean by "at a given pulse"?
  • How will you identify the pulse that matters?
  • What is the typical duration of the pulse?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

PaulS

People that talk about code being slow, and then post code with delay() in just make me laugh and head for the next topic.
The art of getting good answers lies in asking good questions.

Jonarotz

Robin
Sorry the details all in my head and didn't make it to the keyboard...the pulse will be an rpm. Obviously the pulse will start at zero and climb. The arduino will will be controlling a relay and switched via Bluetooth.  At a pulse count (yet to be determined) the relay will be deactivated.

Jonarotz

Glad I can make you laugh Paul...move along then.

I went through the code to systematically eliminate things and the delay wasn't the problem with it taking so long. Deleting it made no real difference in the reaction time. It did need the delay to detect the pulse though, without it it couldn't pick it up.

It's people like you that make this difficult to learn with your quick judgments and snarky comments. I'm new to this while you've probably been at it a couple days.
Thanks for your help!

cattledog

Code: [Select]
if (digitalRead(pulse > 10)){

What is this line supposed to do?

Jonarotz

My intention was to read the pulse and if > 10 switch the output LOW

cattledog

#7
Mar 21, 2017, 04:19 am Last Edit: Mar 21, 2017, 05:20 pm by cattledog
Quote
My intention was to read the pulse and if > 10 switch the output LOW
Code: [Select]
void count_pulse() //This defines what the interrupt does
{
  pulse++;
    if (pulse>10)
    {
        digitalWrite(start, LOW);
        pulse = 0: //reset pulse count??
    }

}

Robin2

Sorry the details all in my head and didn't make it to the keyboard...the pulse will be an rpm. Obviously the pulse will start at zero and climb. The arduino will will be controlling a relay and switched via Bluetooth.  At a pulse count (yet to be determined) the relay will be deactivated.
An RPM and a pulse are two very different things. And I have never come across pulses that climb.

Do you mean that you have a wheel that produces one pulse for every revlolution?
And you want to count the pulses (i,e. the number of revolutions?
And you want to stop the wheel turning after a certain number of pulses?

A computer program will only work properly if it is constructed with great precision and it is probably more essential to be very precise when describing the requirement before starting to construct the program.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Jonarotz

An RPM and a pulse are two very different things. And I have never come across pulses that climb.

Do you mean that you have a wheel that produces one pulse for every revlolution?
And you want to count the pulses (i,e. the number of revolutions?
And you want to stop the wheel turning after a certain number of pulses?

A computer program will only work properly if it is constructed with great precision and it is probably more essential to be very precise when describing the requirement before starting to construct the program.

...R
The RPM is a 0-5v  square wave...the amount of waves (pulses in my head) will increase per second as RPM increases.
At a specified RPM or frequency the relay will need to be deactivated. 
The RPM will continue to climb and vary, it will not stop after the relay is deactivated. The operating rpm will just be outside the window I specify.
The rpm I want the relay activated will be more comparable to a cranking speed, once startup occurs (above my specified pulse count) the relay will shut off.

Jonarotz

Code: [Select]
void count_pulse() //This defines what the interrupt does
{
  pulse++;
    if (pulse>10))
    {
        digitalWrite(start, LOW);
        pulse = 0: //reset pulse count??
    }

}

So no need to call a digital.Read...I will try this out.
Thanks for your help.

cattledog

If you want to time your interrupt counts do not use delay. Use the "blink without delay" millis() timer approach. Only disable interrupts briefly to read data. Software Serial requires interrupts to be enabled. I would suggest that you read Nick Gammon's tutorial on interrupts http://www.gammon.com.au/interrupts

Here's an example of timing an interrupt count

Code: [Select]
volatile unsigned long  count = 0;
unsigned long copyCount = 0;

unsigned long lastRead = 0;
unsigned long interval = 1000;//one second

void setup()
{
  Serial.begin(115200);
  Serial.println("start...");
 
  pinMode(2,INPUT_PULLUP);
  attachInterrupt(0, isrCount, RISING); //interrupt signal to pin 2
}

void loop()
{
  if (millis() - lastRead >= interval) //read interrupt count every second
  {
    lastRead  += interval;
    // disable interrupts,make copy of count,reenable interrupts
    noInterrupts();
    copyCount = count;
    count = 0;
    interrupts();
 
    Serial.println(copyCount);

  }
}

void isrCount()
{
  count++;
}

Robin2

The RPM is a 0-5v  square wave...the amount of waves (pulses in my head) will increase per second as RPM increases.
At a specified RPM or frequency the relay will need to be deactivated.  
The RPM will continue to climb and vary, it will not stop after the relay is deactivated. The operating rpm will just be outside the window I specify.
The rpm I want the relay activated will be more comparable to a cranking speed, once startup occurs (above my specified pulse count) the relay will shut off.
Hold on a moment now. This is a very different concept to what I thought we were dealing with.

You now seem to be saying that the interval between pulses represents the speed and it is the speed you are interested in - not the number of pulses.

You need to tell us how many pulses per second correspond with different RPMs and, in particular what is the critical pulse rate that you are interested in.

I have an Arduino controlling a small electric motor with an optical detector that produces a pulse every revolution. My Arduino code records the value of micros() for every pulse and the difference between the current value and the previous value is the number of microsecs for a revolution. A little maths can turn that into RPM.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Jonarotz

If you want to time your interrupt counts do not use delay. Use the "blink without delay" millis() timer approach. Only disable interrupts briefly to read data. Software Serial requires interrupts to be enabled. I would suggest that you read Nick Gammon's tutorial on interrupts http://www.gammon.com.au/interrupts

Here's an example of timing an interrupt count

Code: [Select]
volatile unsigned long  count = 0;
unsigned long copyCount = 0;

unsigned long lastRead = 0;
unsigned long interval = 1000;//one second

void setup()
{
  Serial.begin(115200);
  Serial.println("start...");
 
  pinMode(2,INPUT_PULLUP);
  attachInterrupt(0, isrCount, RISING); //interrupt signal to pin 2
}

void loop()
{
  if (millis() - lastRead >= interval) //read interrupt count every second
  {
    lastRead  += interval;
    // disable interrupts,make copy of count,reenable interrupts
    noInterrupts();
    copyCount = count;
    count = 0;
    interrupts();
 
    Serial.println(copyCount);

  }
}

void isrCount()
{
  count++;
}

I was able to get this to operate how I wanted. I was able to tweak the code you sent above and it worked great.

Also the link was very informative as well.

THANK YOU
THANK YOU
THANK YOU!!!


Go Up