Hi! I am completely new to Arduino and have spent all day going through several posts in the forum to see if I can do what I want. It seems that other people have had success but I cannot seem to get my code to do what I want.
What I'd like to do is receive a signal from an accelerometer and in turn send a signal to a laser and a camera to fire. I need this to happen extremely fast (within 1-2 microseconds at most) because of how fast the airflow I am measuring is (this is for a shock tube). Because of this, I am trying to use an interrupt. But, I need this interrupt to only happen once and only with the initial accelerometer spike because the laser cannot receive more than 1 signal in a 30 second period or the core will melt (lol). Also, I am using an Arduino Due.
Currently, I have gotten the reaction I wanted to an input signal (i.e. the output pin reads HIGH when the input pin reads HIGH), but when I try to add detachInterrupt inside the ISR, it stop responding altogether to any kind of input. I've also tried to use delayMicroseconds in the ISR and a boolean operator outside the ISR to trigger the detachment after the first interrupt, and again, it acts like the code doesn't exist on the Arduino.
I've attached my code below with the detachInterrupt. My question is how do I get this thing to only fire once? Am I on the right track? Do y'all have any suggestions or can you please point me in the right direction? Thank you!
int accelPin = 2; // pin for accelerometer
int laserPin = 12; // pin for laser
// variables that change:
volatile int accelState = LOW;
void setup() {
// initialize the laser pin as an output:
pinMode(laserPin, OUTPUT);
// initialize the accelerometer pin as an input:
pinMode(accelPin, INPUT);
// attach an interrupt:
attachInterrupt(digitalPinToInterrupt(2), pin_ISR, HIGH);
}
void loop() {
}
void pin_ISR () {
accelState = digitalRead(accelPin);
digitalWrite(laserPin, accelState); // output val = input val
delayMicroseconds(500);
detachInterrupt(2);
}
void pin_ISR () {
if (armed)
{
accelState = digitalRead(accelPin);
digitalWrite(laserPin, accelState); // output val = input val
armed = false;
}
}
aarg, thanks!
I tried this, adding volatile bool armed = false
underneath my //variables that change, and it accepted it, but for some reason, the interrupt is still firing after the first signal is received. I tried to do 'if' statements earlier today, and it seemed like the boolean operators were only changing while it was receiving the input and then going back to the original value after I stopped supplying the signal.
Post your new code. The entire sketch.
int accelPin = 2; // pin for accelerometer
int laserPin = 12; // pin for laser
// variables that change:
volatile int accelState = LOW;
volatile bool armed = true;
void setup() {
// initialize the laser pin as an output:
pinMode(laserPin, OUTPUT);
// initialize the accelerometer pin as an input:
pinMode(accelPin, INPUT);
// attach an interrupt:
attachInterrupt(digitalPinToInterrupt(2), pin_ISR, HIGH);
}
void loop() {
}
void pin_ISR () {
if (armed = true)
{
accelState = digitalRead(accelPin);
digitalWrite(laserPin, accelState); // output val = input val
armed = false;
}
}
Without the if (armed=true)
it would not change at all and without the volatile bool armed = true
it would throw an error. That's why I added those things, but, again, I'm new, so idk if that's entirely correct or not.
It's
if (armed==true)
or if (armed)
not
if (armed=true)
Ah ok! Thank you! I really appreciate you helping and getting back to me so quickly!
I uploaded it and tried again and
it still is not changing value with an input. I've checked my wiring and everything too just in case something came loose and that does not seem to be the problem.
int accelPin = 2; // pin for accelerometer
int laserPin = 12; // pin for laser
// variables that change:
volatile int accelState = LOW;
volatile bool armed = true;
void setup() {
// initialize the laser pin as an output:
pinMode(laserPin, OUTPUT);
// initialize the accelerometer pin as an input:
pinMode(accelPin, INPUT);
// attach an interrupt:
attachInterrupt(digitalPinToInterrupt(2), pin_ISR, HIGH);
}
void loop() {
}
void pin_ISR () {
if (armed==true)
{
accelState = digitalRead(accelPin);
digitalWrite(laserPin, accelState); // output val = input val
armed = false;
}
}
Why digitalRead on accelPin when only a HIGH on that pin will cause an interrupt? Does the laser turn off by itself? You never turn it off.
Good question. This code is technically a modified version of a code I found here: Controlling a Camera Shutter Remotely with an Arduino – Norwegian Creations
digitalWrite(laserPin, accelState);
vs digitalWrite(laserPin, HIGH);
I get a constant HIGH value output regardless of the input if I use the later code.
Sorry, I just saw the rest of the question, but the laser turning off is actually not my problem to deal with hahaha I'm working with people from a laser lab and they do all the laser stuff, I'm just trying to interface the initial signal and trying not to overheat their core. I'm not sure how long the laser actually runs, I just know it's capable of 1000 pulses per microsecond and cannot receive more than one signal to "go" in a 30 second time period. I know its capable of remaining on for awhile because I've seen them aligning it, but I don't know how it turns off, just that I don't have to include that in my code. I almost want to say that they have to turn it off manually after the run is over.
So I tried Serial.print to check the status of "armed" and it only outputs a value of 0, false, while the arduino is receiving a signal. Because it's false, the output value does not change. What I'm not understanding is why it's only outputting when the interrupt is triggered? I thought putting the boolean variable at the very top, outside of void loop() made it a global variable?
int accelPin = 2; // pin for accelerometer
int laserPin = 12; // pin for laser
// variables that change:
volatile int accelState = LOW;
volatile bool armed = true;
void setup() {
// initialize the laser pin as an output:
pinMode(laserPin, OUTPUT);
// initialize the accelerometer pin as an input:
pinMode(accelPin, INPUT);
// attach an interrupt:
attachInterrupt(digitalPinToInterrupt(2), pin_ISR, HIGH);
//Initiate Serial communication.
Serial.begin(9600);
}
void loop() {
Serial.print(armed);
}
void pin_ISR () {
if (armed==true)
{
accelState = digitalRead(accelPin);
digitalWrite(laserPin, accelState); // output val = input val
armed = false;
}
}
Another interesting thing happens if I remove the volatile on the boolean armed. Now it outputs false when the interrupt is NOT triggered and stops outputting with the interrupt is triggered. Almost the exact opposite of what happens in the above code. I really don't understand it. I've been looking into it, but no such luck yet. Any suggestions are welcome 
int accelPin = 2; // pin for accelerometer
int laserPin = 12; // pin for laser
// variables that change:
volatile int accelState = LOW;
bool armed = true;
void setup() {
// initialize the laser pin as an output:
pinMode(laserPin, OUTPUT);
// initialize the accelerometer pin as an input:
pinMode(accelPin, INPUT);
// attach an interrupt:
attachInterrupt(digitalPinToInterrupt(2), pin_ISR, HIGH);
// initiate serial communication.
Serial.begin(9600);
}
void loop() {
Serial.print(armed);
Serial.print("\n");
}
void pin_ISR () {
if (armed==true)
{
accelState = digitalRead(accelPin);
digitalWrite(laserPin, accelState); // output val = input val
armed = false;
}
}
Sometimes when you attach an interrupt it will trigger immediately, because the interrupt flag in the processor is set before the attachInterrupt() is executed. This could be triggering a spurious interrupt, outputting a low to the laser and setting armed to false. Try this code, which will only disarm the interrupt when the accelerometer input is HIGH. (Normally you would clear the interrupt flag immediately before the attachInterrupt, but I'm not familiar with the DUE and not sure of the exact command for that particular board);
const byte accelPin = 2; // pin for accelerometer
const byte laserPin = 12; // pin for laser
// variables that change:
volatile bool armed = false;
void setup() {
// initialize the laser pin as an output:
pinMode(laserPin, OUTPUT);
// initialize the accelerometer pin as an input:
pinMode(accelPin, INPUT);
// attach an interrupt:
attachInterrupt(digitalPinToInterrupt(2), pin_ISR, HIGH);
//Initiate Serial communication.
Serial.begin(9600);
}
void loop() {
Serial.print(armed);
}
void pin_ISR () {
if (armed == true) {
if (digitalRead(accelPin) == HIGH) {
digitalWrite(laserPin, HIGH); // output val = input val
armed = false;
}
}
}
I would also be inclined to specifically output a LOW to the laserPin in setup(), just to be clear in the code that it needs to start out as a LOW.
If this doesn't work, can you give more information on the accelerometer and how it is connected to the arduino? A floating input will cause all sorts of problems if the accelerometer has an open collector type output and you don't use a pullup resistor.