Hey all,
I have been making a code for triggering an RC tank cannon. The cannon works by running a motor that loads a spring and as that spring is unloaded and fires a BB, a switch closes for a fraction of time.
The detection is done via an interrupt pin. At the same time there are a few states in which the cannon can operate. Detection of the interrupt is now only in the FIRING state as there the motor runs. In the READY state a fire command can be given, in which the attachInterrupt is set.
The issue I have is that after a succesful firing, the motor stops after receiving a valid feedback. If I then give a second fire command (after a minute or two), the state goes to FIRING, but receives an immediate interrupt with barely any movement of the motor. The command after is succesful again.
The second interrupt does not happen with a contact being made of the feedback circuit, so I expect it is in the way I have the code set up.
I have been making use of threading, but this is with other code that I want to add in the future.
Does someone have an idea where the issue might be?
/ ********************************************************************************
DESCRIPTION:
This is the test code for testing the Fire control function.
The firing of turret is controlled via a state machine.
The feedback of firing is received via resistance to ground switch circuit.
An interrupt on the feedback trigger is used for determining fired status.
CONNECTIONS (Arduino nano v3 - Atmega328P, old bootloader):
Arduino 13 - Digital output fire motor control - ULN2001AN/(4-6B) via ..Ω
Arduino 02 - Digital input fired feedback (on interrupt pin)
*******************************************************************************/
// Libraries
#include <Thread.h>
#include <ThreadController.h>
// Define pins
const int fireMotorPin = 13; // Darlington transistor controlled via D13
const int fireFeedbackPin = 2; // Feedback pin on interrupt pin
// Threads
ThreadController master = ThreadController(); // ThreadController
Thread* mainThread = new Thread(); // Thread as a pointer (longest time)
Thread cannonThread = Thread();
// Finite State Machine (FSM)
enum FireState {
IDLE,
READY,
FIRING,
FIRED
};
FireState state = FireState::IDLE; // Initial state FSM
// Parameters
bool enableCannon;
bool fireCommand;
volatile boolean fireFeedbackReceived = false;
// Keyboard assignment for fire control
#define ENABLE_CMD 'E'
#define FIRE_CMD 'F'
#define STOP 'S'
// Initialisation
void setup() {
Serial.begin(9600);
// pinout Fire control
pinMode(fireMotorPin, OUTPUT);
pinMode(fireFeedbackPin, INPUT_PULLUP);
enableCannon = false;
fireCommand = false;
digitalWrite(fireMotorPin, LOW);
// Start Threads
mainThread->onRun(keyboard_ctrl);
mainThread->setInterval(500);
//
cannonThread.onRun(fire_ctrl);
cannonThread.setInterval(20);
//
master.add(mainThread);
master.add(&cannonThread); // & to pass the pointer to it
}
// Functions
void fireFeedbackInterrupt() {
// Detach interrupt routine
detachInterrupt(digitalPinToInterrupt(fireFeedbackPin));
fireFeedbackReceived = true;
Serial.println("interrupt");
}
// Function to control Fire motor based on FSM
void fire_ctrl() {
// State switching
switch (state) {
case FireState::IDLE:
// transition to READY if cannon enabled
// Serial.println("IDLE");
if (fireCommand) {
fireCommand = false;
}
if (enableCannon) {
state = FireState::READY;
}
break;
case FireState::READY:
// Listen for fire command
// Serial.println("READY");
if (fireCommand) {
fireCommand = false;
// Attach interrupt routine
attachInterrupt(digitalPinToInterrupt(fireFeedbackPin), fireFeedbackInterrupt, FALLING);
state = FireState::FIRING;
}
if (!enableCannon) {
state = FireState::IDLE; // Transition to IDLE when safety is not enabled
}
break;
case FireState::FIRING:
Serial.println("FIRING");
digitalWrite(fireMotorPin, HIGH);
if(fireFeedbackReceived){
state = FireState::FIRED;
};
break;
case FireState::FIRED:
digitalWrite(fireMotorPin, LOW);
Serial.println("FIRED");
fireFeedbackReceived = false;
// After firing back to ready
state = FireState::READY;
break;
}
}
void keyboard_ctrl(){
char byte = 0;
// press z to cancel and exit
Serial.readBytes(&byte, 1);
// FIRE CONTROL VIA KEYBOARD CONTROL
// -----------------------------------
// press S to ENABLE SAFETY cannon
if (byte == STOP) {
//Enable Safety for cannon
enableCannon = false;
Serial.print("Command: SAFETY ON \n");
}
// press E for DISABLE SAFETY cannon
if (byte == ENABLE_CMD) {
//Disable Safety for cannon
enableCannon = true;
Serial.print("Command: SAFETY OFF \n");
}
// press F for Firing command cannon
if (byte == FIRE_CMD) {
//Set Fire command
Serial.print("Command: Firing \n");
fireCommand = true;
}
// press z for Exit
if (byte == 'z'){
Serial.print("Done \n");
Serial.end();
}
}
void loop() {
master.run(); // run thread controller
}