Hi,
I am trying to write code that allows for an Arduino Uno to read several buttons pins, run a bipolar stepper motor via the Pololu 36v4 driver and finally trigger a camera shutter in time with each 360° revolution of the motor. I successfully wrote a version that did all these using delay functions but the camera wasn’t getting triggered on time reliably and the motor was running very loudly and jerkily. IT just didn’t seem right. So I’ve tried re-writing my sketch using only timers to avoid blocking functions, but I can’t get it to work. Now the buttons are completely unresponsive. Does anyone see where I’ve gone wrong?
//========= LIBRARIES ===============================================================
#include <SPI.h>
#include <HighPowerStepperDriver.h>
//======== CONSTANTS ================================================================
// 36v4 pins (motor driver)
const uint8_t DirPin = 9;
const uint8_t StepPin = 10;
const uint8_t CSPin = 8;
const int RESpin = 6;
const int SLEpin = 7;
const int FLTpin = 5;
HighPowerStepperDriver sd;
// constant intervals
const int buttonInterval = 500000; // number of millisecs between button readings
const int StepDelayInterval = 3; // compare this to micros
const int GH5_interval = 3000; // adjust based on GH5 trigger response time
unsigned long print_interval = 500000;
const uint16_t StepPeriodUs = 200; // controls speed of stepper motor
const int StepsPerRev = 2000; // maybe try setting this the effective gear ratio of one frame?
// telecine/camera controls
const int motorStartPin = 4;
const int motorDirPin = 3;
const int cameraTriggerPin = 2;
//======== VARIABLES ================================================================
unsigned long currentMicros = 0;
unsigned long previousMotorStartMicros = 0; // time when button press last checked
unsigned long previousDirMicros = 0; // time when button press last checked
unsigned long previousPrintMicros = 0;
unsigned long StepTime_a = 0;
unsigned long StepTime_b = 0;
unsigned long TriggerTime_a = 0;
unsigned long TriggerTime_b = 0;
byte cameraTrigger_State = LOW;
byte motor_State = LOW;
byte dir_State = LOW;
unsigned long stepCount = 0;
unsigned long frameCount = 0;
unsigned long triggerCount = 0;
//===================================================================
void setup() {
SPI.begin();
sd.setChipSelectPin(CSPin);
Serial.begin(9600);
pinMode(StepPin, OUTPUT);
digitalWrite(StepPin, LOW);
pinMode(DirPin, OUTPUT);
digitalWrite(DirPin, LOW);
pinMode(cameraTriggerPin, OUTPUT);
digitalWrite(cameraTriggerPin, LOW);
pinMode(SLEpin, OUTPUT);
digitalWrite(SLEpin, HIGH);
pinMode(RESpin, OUTPUT);
digitalWrite(RESpin, LOW);
pinMode(FLTpin, INPUT);
pinMode(motorStartPin, INPUT_PULLUP);
pinMode(motorDirPin, INPUT_PULLUP);
delay(1);
sd.resetSettings();
sd.clearStatus();
sd.setDecayMode(HPSDDecayMode::AutoMixed);
sd.setCurrentMilliamps36v4(1700);
sd.setStepMode(HPSDStepMode::MicroStep8);
sd.enableDriver();
}
void loop() {
currentMicros = micros();
readMotorToggle();
readDirToggle();
setDir();
advanceOneFrame();
triggerCamera();
updateFrameCount();
printInfo();
}
//Action functions bellow (called in the loop above)
//===================================================================
void readMotorToggle() {
if (micros() - previousMotorStartMicros >= buttonInterval) {
if (digitalRead(motorStartPin) == LOW) {
motor_State = HIGH;
previousMotorStartMicros = micros();
}
}
else {
if (digitalRead(motorStartPin) == HIGH) {
motor_State = LOW;
}
}
}
//===================================================================
void readDirToggle() {
if (micros() - previousDirMicros >= buttonInterval) {
if (digitalRead(motorDirPin) == LOW) {
dir_State = HIGH;
previousDirMicros = micros();
}
}
else {
if (digitalRead(motorDirPin) == HIGH) {
dir_State = LOW;
}
}
}
//===================================================================
void setDir() {
if(dir_State == HIGH) {
setDirection(0);
}
else {
if(dir_State == LOW) {
setDirection(1);
}
}
}
//===================================================================
void setDirection(bool dir) {
delayMicroseconds(1);
digitalWrite(DirPin, dir);
delayMicroseconds(1);
}
//===================================================================
void advanceOneFrame() {
if (motor_State == HIGH) {
for(int x = 0; x < StepsPerRev; x++){ //change value of StepsPerRev to be one frame
StepTime_a = micros();
digitalWrite(StepPin, HIGH);
stepCount ++;
while(micros() - StepTime_a < StepDelayInterval){
// do nothing
}
StepTime_b = micros();
digitalWrite(StepPin, LOW);
while(micros() - StepTime_b < StepDelayInterval + StepPeriodUs){
// do nothing
}
}
}
}
//===================================================================
void triggerCamera() {
if (motor_State == HIGH) {
TriggerTime_a = micros();
digitalWrite(cameraTriggerPin, HIGH);
triggerCount ++;
while(micros() - TriggerTime_a <= GH5_interval){
}
TriggerTime_b = micros();
digitalWrite(cameraTriggerPin, LOW);
while(micros() - TriggerTime_b <= GH5_interval){
}
}
}
//===================================================================
void updateFrameCount() {
frameCount = stepCount/StepsPerRev;
}
//===================================================================
void printInfo() {
if (micros()-previousPrintMicros >= print_interval) {
Serial.print("Motor State: ");
Serial.println(motor_State);
Serial.print("Direction: ");
Serial.println(dir_State);
Serial.print("Frames: ");
Serial.println(frameCount);
Serial.print("Trigger Count: ");
Serial.println(triggerCount);
Serial.println();
previousPrintMicros = micros();
} else {
if (micros()-previousPrintMicros < print_interval) {
}
}
}
//======================================== END ===========================